JQuery selector source code (3): tokenize method, jquerytokenize

Source: Internet
Author: User

JQuery selector source code (3): tokenize method, jquerytokenize

/** The tokenize method is the core function of selector parsing, which converts the selector into two-level array groups * example: * If the selector is "div. class, span, the parsed result is: * group [0] [0] = {type: 'tag', value: 'div ', matches: match} * group [0] [1] = {type: 'class', value :'. class ', matches: match} * group [1] [0] = {type: 'tag', value: 'span', matches: match} * can be seen from the above results, the parsing result of each element of the groups selector block separated by commas. * In addition, matches in the above results equals the results of pattern matching, because it is not convenient to clearly write here, * only the code matches: match is written here. ** The tokenize method performs the following two main tasks: * 1. The resolution selector * 2. Saves the resolution result to the cache, if *** @ param selector is used for parsing the selector string * @ param parseOnly is true, this call matches the sub-selector. * For example: if the initial selector is "div: not (. class: not (: eq (4): eq (3) "* The code first matches the TAG selector div. * then, the matched pseudo selector string is: not (. class: not (: eq (4): eq (3), * the code will put ". class: not (: eq (4): eq (3 "is used as the value in the brackets of not for further parsing. * When the code calls tokenize resolution, the parseOnly parameter is set to true. */function tokenize (selector, parseOnly) {var matched, Match, tokens, type, soFar, groups, preFilters, // obtain the cached result cached = tokenCache [selector + ""]; /** if there is a selector resolution result in the cache *, execute the if statement body */if (cached) {// if the initial selector is parsed (parseOnly! = True), the cache result is returned. // if not, 0 return parseOnly? 0: cached. slice (0);}/** because strings are not processed as objects in javascript, * by assigning values, the code automatically copies a new string to soFar, * In this way, any processing of soFar will not affect the original data of selector */soFar = selector; groups = []; // assign a value here, which is only used to reduce the number of words in subsequent code, shorten the execution path preFilters = Expr. preFilter; while (soFar) {// Comma and first run/** rcomma = new RegExp ("^" + whitespace + "*," + whitespace + "*") * rcomma is used to determine whether multiple selector blocks exist, that is, multiple parallel selectors separated by commas. ** The following conditions are determined in sequence :*! Matched: true if the loop body is executed for the first time; otherwise, false. * Matched indicates whether to execute the loop body for the first time. * It also indicates whether soFar starts with an invalid string (that is, an invalid single selector) in this loop. * (Match = rcomma.exe c (soFar): gets matching items that match rcomma */if (! Matched | (match = rcomma.exe c (soFar) {if (match) {// Don't consume trailing commas as valid/** remove the first comma and all previous characters * For example: * If the initial selector is: "div. news, span. closed ", * in the parsing process, the div is first parsed by the subsequent code. news, left ", span. when closed "* is executed here in the loop body, delete the comma and the previous consecutive blank space (match [0]), and * Change soFar to" span. closed ", continue to execute the parsing process ** here, if the last non-blank character of the initial selector is a comma, * the soFar remains unchanged when the following code is executed, that is, soFar. slice (match [0]. length) returns an empty string. * The final returned result is | soFar */soFar = soFar. Slice (match [0]. length) | soFar;}/** assign tokens to an empty array when you first execute the loop body or encounter a comma delimiter, and * press it into the groups array */groups. push (tokens = []);} matched = false; // Combinators/** rcombinators = new RegExp (* "^" + whitespace + "* ([> ++] | "+ Whitespace +") "+ whitespace +" * "), * rcombinators is used to match four types of Relational operators, that is,> + ~ And blank ** if soFar starts with a relational character, execute the statement body in if */if (match = rcombinators.exe c (soFar ))) {/** remove the match array from match [0] and assign it to matched * If the original link character has spaces on both sides, in this case, match [0] and matched are not equal. * For example: * If soFar = "+. div "; * after executing match = rcombinators.exe c (soFar), * match [0] =" + ", while match [1] =" + "; * matched = match. after shift (), * matched = "+", while match [0] = "+"; */matched = match. shift (); // press the matching result into the tokens array. push ({value: matched, // Cas T descendant combinators to space/** rtrim = new RegExp ("^" + whitespace + "+ | ((?: ^ | [^ \\\\]) (? :\\\\.) *) "* + Whitespace +" + $ "," g "), * whitespace =" [\ x20 \ t \ r \ n \ f] "; ** match [0] below. replace (rtrim, "") is used to replace the blank spaces on both sides of match [0] With Spaces * but because of the match on it. shift function. match [0] is already a string with no blank strings on both sides. * The replacement is useless Code */type: match [0]. replace (rtrim, "")}); // assign the character string after the link character to soFar and continue parsing soFar = soFar. slice (matched. length);} // Filters/** use the for statement to match the IDs, tags, CLASS, CHILD, ATTR, and PSEUDO selector of soFar one by one. * If the selector matches, the pre-filter function corresponding to the selector of this type is called first., * Then, press the result into the tokens array to continue this loop. */For (type in Expr. filter) {/** match = matchexpr?type=.exe c (soFar): Call the regular expression of type to match soFar, and assign the matching result to match. If no data is matched, match is undefined. *! PreFilters [type]: If the type pre-filter function does not exist, true * match = preFilters [type] (match): pre-filter is executed, and return the result to match **/if (match = matchexpr1_type.exe c (soFar ))&&(! PreFilters [type] | (match = preFilters [type] (match) {// remove match [0] from the match array and assign it to matchedmatched = match. shift (); // press the matching result into the tokens array. push ({value: matched, type: type, matches: match}); // assign the matched strings to soFar and continue parsing soFar = soFar. slice (matched. length) ;}}/** if matched = false, * indicates that this cycle does not have a valid selector (including the type selectors such as the link operator and id and class) * therefore, soFar resolved to the current position is an invalid selector string * jumps out of the while LOOP body */if (! Matched) {break ;}// Return the length of the invalid excess // if we're re just parsing // Otherwise, throw an error or return tokens/** if the initial selector string is not parsed (! ParseOnly = true), * returns soFar. length, soFar. length indicates the final position of the continuous valid selector. * Subsequent articles will describe the instance. * If the initial selector string is parsed, check whether soFar has any characters. * If yes, execute Sizzle. error (selector) throws an exception. * If not, tokenCache (selector, groups) is executed ). slice (0) pushes the result into the cache and returns a copy of the result. */Return parseOnly? SoFar. length: soFar? Sizzle. error (selector): // Cache the token=encache (selector, groups). slice (0 );}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.