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