JQuery. clean source code analysis includes: jQuery. clean usage, Train of Thought Analysis, and source code annotation analysis. If you are interested, refer
I. jQuery. clean usage
JQuery. clean (elems, context, fragment, scripts );
Ii. Train of Thought Analysis
1. process the context parameter and make sure it is the document root node.
2. Processing Parameter elems array (looping array)
2.1. elem is a number and converted to a string
2.2. elem is invalid and jumps out of this loop.
2.3. elem is a string
2.4 if no entity ID or html Tag exists in the string, the text node is created.
2.5. The string is the entity ID or html Tag.
The Code is as follows:
Create a p element and insert it to the file fragment.
Processing xhtml style labels
Wrap elem and use the wrapped string as the innerHTML of p.
If the package depth is greater than 1, only the first package element is left
Clear the tbody automatically added to the ie6 and 7 empty table labels.
Use the leading blank string removed from the browsers earlier than ie9 as the first text subnode of the p element.
Assign a new value to elem as a subnode set of p (nodeList object ),
Remove p from the File Fragment in this loop and keep the p element clean in the next loop.
2.3 If elem is a text node, it is directly added to the ret array to be returned. Otherwise, nodes in elem (nodeList object) are merged to the array.
2.4. Fixed the bug where the node type in ie6 and 7 is radio and the checkbox node status (checked) fails.
3. Processing Parameter fragment
3.1 add nodes in ret to fragment
3.2 extract the script subnode from the node and add it to the ret array. The script position is after the position of the original parent element.
4. Return the ret Array
Iii. source code annotation Analysis
1. Variables and functions used in Functions
The Code is as follows:
Var nodeNames = "abbr | article | aside | audio | bdi | canvas | data | datalist | details | figcaption | figure | footer |" +
"Header | hgroup | mark | meter | nav | output | progress | section | summary | time | video ",
WrapMap = {
Option: [1 ,"",""],
Legend: [1 ,"
"," "],
Thead: [1 ,"
"],
Tr: [2 ,"
"],
Td: [3 ,"
"],
Col: [2 ,"
"],
Area: [1 ," ",""],
_ Default: [0, "", ""]
},
RxhtmlTag =/<(?! Area | br | col | embed | hr | img | input | link | meta | param) ([\ w:] +) [^>] *) \/>/gi,
RtagName =/<([\ w:] + )/,
Rtbody =/Rhtml =/<| &#? \ W + ;/,
RleadingWhitespace =/^ \ s + /,
RcheckableType =/^ (? : Checkbox | radio) $ /,
RscriptType = // (java | ecma) script/I;
// Set the default selection status of the checkbox or single-member radio form Element
Function fixDefaultChecked (elem ){
If (rcheckableType. test (elem. type )){
Elem. defaultChecked = elem. checked;
}
}
// Create a secure document Fragment
Function createSafeFragment (document ){
Var list = nodeNames. split ("| "),
SafeFrag = document. createDocumentFragment (); // ie6, the browser uses safeFrage as the HTMLDocument type
// For browsers earlier than ie9
If (safeFrag. createElement ){
While (list. length ){
SafeFrag. createElement (
List. pop ()
);
}
}
Return safeFrag;
}
// Simulate new functions of Array in ES5
// The function API: http://www.css88.com/jqapi-1.8/#p=jQuery.grep
JQuery. extend ({
Grep: function (elems, callback, inv ){
Var retVal,
Ret = [],
I = 0,
Length = elems. length;
Inv = !! Inv;
// Go through the array, only saving the items
// That pass the validator function
For (; I <length; I ++ ){
RetVal = !! Callback (elems [I], I );
If (inv! = RetVal ){
Ret. push (elems [I]);
}
}
Return ret;
}
});
2. Source Code Analysis
The Code is as follows:
JQuery. extend ({
Clean: function (elems, context, fragment, scripts ){
// Declare Variables
Var I, j, elem, tag, wrap, depth, p, hasBody, tbody, len, handleScript, jsTags,
Safe = context === document & safeFragment,
Ret = [];
// Make sure that the variable context is the document root node document
If (! Context | typeof context. createDocumentFragment = "undefined "){
Context = document;
}
// Use the already-created safe fragment if context permits
For (I = 0; (elem = elems [I])! = Null; I ++ ){
// If elem is a number, convert it to a string
If (typeof elem = "number "){
Elem + = "";
}
// If elem is undefined, it will jump out of this loop.
If (! Elem ){
Continue;
}
// Convert html string into DOM nodes
// Convert an array item (string) to a DOM Node
If (typeof elem = "string "){
// If the html Entity number or tag does not exist, a text node is created.
If (! Rhtml. test (elem )){
Elem = context. createTextNode (elem );
}
// Processing is an array of html Tag strings
Else {
// Ensure a safe container in which to render the html
// Safe is # document-fragment type. In browsers earlier than ie9, safe is an HTMLDocument node and the nodeNames array is empty.
Safe = safe | createSafeFragment (context );
// Create a p element and insert it into the File Fragment
P = context. createElement ("p ");
Safe. appendChild (p );
// Fix "XHTML"-style tags in all browsers
// In addition to tags such as area, br, col, embed, hr, img, input, link, meta, And param,
// Convert the label with a slash added at the end of the start tag to the start and end tags
Elem = elem. replace (rxhtmlTag, "<$1> ");
// Go to html and back, then peel off extra wrappers
// Obtain the first Tag Element on the left
Tag = (rtagName.exe c (elem) | ["", ""]) [1]. toLowerCase ();
// Obtain the package element of the outermost element and enclose the element in it
Wrap = wrapMap [tag] | wrapMap. _ default;
Depth = wrap [0];
P. innerHTML = wrap [1] + elem + wrap [2];
// Move to the right depth
// If the package depth of an element is greater than 1, p is assigned to the nearest package element (that is, containing the first package element)
While (depth --){
P = p. lastChild;
}
// Remove IE's autoinsertedFrom table fragments
// In IE6, 7, clear the tbody tag automatically added to the string empty table tag (unless manually added)
If (! JQuery. support. tbody ){
// String was
, * May * have spurious (forged)
// Determine whether the string contains a null tbody tagHasBody = rtbody. test (elem );// If the outermost tag is table and the tbody is not manually added to the table// Variable tbody: p. firstChild. childNodes (automatically added tbody tag set)Tbody = tag = "table "&&! HasBody?P. firstChild & p. firstChild. childNodes:// String was a bare
Or
// If the string contains only one empty thead or tfoot tag// Variable tbody is p. childNodes (Set of thead and tfoot tags in the string)Wrap [1] ="
"&&! HasBody?P. childNodes:[];For (j = tbody. length-1; j> = 0; -- j ){// Exclude thead or tfoot tagsIf (jQuery. nodeName (tbody [j], "tbody ")&&! Tbody [j]. childNodes. length ){// Clear the tbody automatically added to the empty table labelTbody [j]. parentNode. removeChild (tbody [j]);}}}// IE completely kills leading whitespace when innerHTML is used// In the browser below ie9, the string starts with a blank string and uses the blank string as the first file subnode of the p element.If (! JQuery. support. leadingWhitespace & rleadingWhitespace. test (elem )){P. insertBefore (context. createTextNode (rleadingWhitespace.exe c (elem) [0]), p. firstChild );}// Obtain the processed p subnode set (nodeList object)Elem = p. childNodes;// Take out of fragment container (we need a fresh p each time)// Clear the p element that has been created before processing the string array in the next loopP. parentNode. removeChild (p );}}// If elem is a DOM node (text node)If (elem. nodeType ){Ret. push (elem );}// Merge the nodes in the nodeList object into the returned arrayElse {JQuery. merge (ret, elem );}}// Fix #11356: Clear elements from safeFragmentIf (p ){Elem = p = safe = null;}// Reset defaultChecked for any radios and checkboxes// About to be appended to the DOM in IE 6/7 (#8060)// In ie6, 7, the single-choice button with the checked attribute. After the check box is inserted to another label, the selected status will expire (the following code fixes this bug)If (! JQuery. support. appendChecked ){For (I = 0; (elem = ret [I])! = Null; I ++ ){If (jQuery. nodeName (elem, "input ")){Fixdefacheckchecked (elem );} Else if (typeof elem. getElementsByTagName! = "Undefined "){JQuery. grep (elem. getElementsByTagName ("input"), fixdefacheckchecked );}}}// Append elements to a provided document fragment// Insert each DOM node in the ret array into the provided document Fragment// Extract the script node from the dom node and add it to the ret array. After the position is the index position of its original parent elementIf (fragment ){// Special handling of each script elementHandleScript = function (elem ){// Check if we consider it executable// If the elem element does not have the type attribute or the type value is javascript or ecmascriptIf (! Elem. type | rscriptType. test (elem. type )){// Detach the script and store it in the scripts array (if provided) or the fragment// Return truthy to indicate that it has been handledReturn scripts?Scripts. push (elem. parentNode? Elem. parentNode. removeChild (elem ):Fragment. appendChild (elem );}};For (I = 0; (elem = ret [I])! = Null; I ++ ){// Check if we're done after handling an executable scriptIf (! (JQuery. nodeName (elem, "script") & handleScript (elem ))){// Append to fragment and handle embedded scripts// Add the elem element to the File Fragment and process the embedded script (script Tag Element)Fragment. appendChild (elem );If (typeof elem. getElementsByTagName! = "Undefined "){// HandleScript alters the DOM, so use jQuery. merge to ensure snapshot iterationJsTags = jQuery. grep (jQuery. merge ([], elem. getElementsByTagName ("script"), handleScript );// Splice the scripts into ret after their former ancestor and advance our index beyond them// Add the script tag to the array after the index position of its original parent ElementRet. splice. apply (ret, [I + 1, 0]. concat (jsTags ));I + = jsTags. length;}}}}Return ret;}});