jQuery selector source code interpretation (iv) : Expr.preFilter tokenize method

  • 2020-05-24 05:08:19
  • OfStack

Expr.preFilter is a method to preprocess the three selectors of ATTR, CHILD and PSEUDO in tokenize method. The details are as follows:


Expr.preFilter : {
	"ATTR" : function(match) {
		/*
		 *  Complete the following tasks: 
		 * 1 , attribute name decoding 
		 * 2 , attribute value decoding 
		 * 3 , if the judge is ~= , then add a space to both sides of the property value 
		 * 4 , return to final mtach object 
		 * 
		 * match[1] Represents the property name, 
		 * match[1].replace(runescape, funescape) : put the property in the name 106 The base number is decoded 
		 *    single-byte unicode Character or double byte unicode Character (Chinese or other text that requires two bytes of representation) 
		 *  For a detailed explanation of regular expressions, see my "elaboration. jQuery Selector regular expressions "article 
		 */
		match[1] = match[1].replace(runescape, funescape);

		/*
		 *  Decodes the attribute value 
		 * match[4] : represents the value of an attribute in single or double quotation marks 
		 * match[5]:  Represents an attribute value that is not enclosed in quotation marks 
		 */
		match[3] = (match[4] || match[5] || "").replace(runescape,
				funescape);

		/*
		 * ~= The meaning is word matching, in W3C The definition of a word in "white space" is the separator of different words 
		 *  Therefore in match[3] After adding space to both sides, you can use indexOf , and correctly identify the presence or absence of the word 
		 */
		if (match[2] === "~=") {
			match[3] = " " + match[3] + " ";
		}

		/*
		 *  Return the useful one 4 Individual element result 
		 */
		return match.slice(0, 4);
	},

	"CHILD" : function(match) {
		/*
		 *  Complete the following tasks: 
		 * 1 , in the command child and of-type The previous character becomes lowercase 
		 * 2 And for the nth The opening selector checks for the validity of the data in parentheses 
		 * 3 , match[4] and match[5] Stored separately xn+b In the x and b . x and b Allowed to be negative 
		 * 4 , return to final match object 
		 * 
		 * match[1] : (only|first|last|nth|nth-last) In the 1 a 
		 */
		match[1] = match[1].toLowerCase();

		/*
		 *  for nth-child , nth-of-type , nth-last-child , nth-last-of-type4 Each type of bracket needs to set valid data 
		 *  Others are not allowed to have any data in parentheses 
		 */
		if (match[1].slice(0, 3) === "nth") {
			/*
			 *  If there are no valid arguments in the selector brackets, an exception is thrown 
			 *  Example: if the selector is nth or nth(abc) Is an illegal selector 
			 */
			if (!match[3]) {
				Sizzle.error(match[0]);
			}
			/*
			 *  The first to nth-child() As an example to introduce 1 Use the following syntax to better understand what the following code does 
			 * nth-child Several usage modes are allowed as follows: 
			 * 	 :nth-child(even)
			 * 	 :nth-child(odd)
			 * 	 :nth-child(3n)
			 * 	 :nth-child(+2n+1)
			 * 	 :nth-child(2n-1)
			 *  To the left of the assignment number in the following code match[4] , match[5] Used to record the parenthesis separately n Before and n The latter value, including the plus or minus sign 
			 *  for :nth-child(even) and :nth-child(odd) Speaking, match[4] Is empty, 
			 *    So back  2 * (match[3] === "even" || match[3] === "odd") Calculated results of 
			 *    Because in the js In the true=1,false=0 , so (match[3] === "even" || match[3] === "odd") Is equal to the 1
			 *    As a result, 2 * (match[3] === "even" || match[3] === "odd") Is calculated as 2
			 * 
			 *  On the right hand side of the equal sign, + "Is used to cast a string into a numeric value  
			 */
			match[4] = +(match[4] ? match[5] + (match[6] || 1)
					: 2 * (match[3] === "even" || match[3] === "odd"));
			match[5] = +((match[7] + match[8]) || match[3] === "odd");

		} else if (match[3]) {
			/*
			 *  Were it not for nth The rest of the beginning CHILD The type selector with parentheses throws an exception 
			 *  Here, jQuery It's not strictly followed W3C The rule to determine as it allows :first-child() This form exists 
			 *  That is, for jQuery for :first-child() Is equivalent to :first-child Is a legal selector 
			 */
			Sizzle.error(match[0]);
		}

		return match;
	},

	"PSEUDO" : function(match) {
		/*
		 *  Complete the following tasks: 
		 * 1 , gets the value of the pseudo-class enclosed in quotation marks 
		 * 2 , for non-quoted values, if there is a pseudo-class nested, into 1 Step resolution determines the actual end position of the current pseudo-class, 
		 *   Gets the full string and value of the current pseudo-class 
		 * 3 , return match In the first 3 A copy of the item. 
		 * 
		 * unquoted Represents a value in parentheses that is not enclosed in quotation marks, 
		 *  In order to :eq(2) For example, unquoted=2
		 */
		var excess, unquoted = !match[5] && match[2];

		/*
		 *  because pseudo with child The matching regular expression has an intersection, so it needs to be put into child I'm going to ignore that 
		 */
		if (matchExpr["CHILD"].test(match[0])) {
			return null;
		}
		/*
		 *  Use quotation marks for values in parentheses (match[3]) In brackets, 
		 *  The value is enclosed in quotes (match[4]) Assigned to match[2] . 
		 * match[3] For quotation marks. 
		 */
		if (match[3] && match[4] !== undefined) {
			match[2] = match[4];
		} else if (unquoted
				/*
				 * rpseudo.test(unquoted) : used for testing unquoted Whether it contains pseudo-classes, 
				 *  If the pseudo-class is included, it indicates that there may be the possibility of nested pseudo-classes, which needs to be entered 1 Step on the unquoted parsing 
				 *  Such as:  :not(:eq(3))
				 */
				&& rpseudo.test(unquoted)
				&&
				/*
				 *  To obtain unquoted The last of the continuously valid selectors 1 The position of the characters 
				 */
				(excess = tokenize(unquoted, true))
				&&
				/*
				 * unquoted.indexOf(")", unquoted.length - excess)
				 *    Continuously valid selector obtained from before last 1 Is found after the position of ")" The location, 
				 *    Usually right after the current position. 
				 *  subtracting unquoted.length , used to obtain match[0] The last position of the valid and complete pseudo-class string in 
				 *    Notice that at this point excess is 1 A negative value 
				 * 
				 */
				(excess = unquoted.indexOf(")", unquoted.length
						- excess)
						- unquoted.length)) {

			//  Gets a valid full pseudo-class match[0] And pseudo-class data in parentheses match[2]
			match[0] = match[0].slice(0, excess);
			match[2] = unquoted.slice(0, excess);
		}

		//  return match before 3 A copy of an element 
		return match.slice(0, 3);
	}
}


Related articles: