jQuery-1.9.1 Source Analysis Series (ii) jquery selector cont.

Source: Internet
Author: User
Tags script tag tagname

Before the analysis, say a little off-topic.

The difference between ownerdocument and documentelement

Ownerdocument is a property of a node object that returns the root node of an element Document object: That is, the document object; DocumentElement is a property of the documents object and returns the root node

For HTML documents, DocumentElement is the element object that corresponds to the

Then get to the point.

1. Several functions encountered in the source code of jquery Selector

A. Analytic functions: Jquery.parsehtml/parsejson/parsexml functions

Jquery.parsehtml (data[, context][, keepscripts]): Parses a string into a collection of DOM nodes

The function itself is not complex. First the data must be a meaningful string, and then the parameter is corrected, since the next two parameters are optional.

if (!data | | typeof data!== "string") {

return null;

}

if (typeof context = = = = "Boolean") {

keepscripts = context;

context = false;

}

It is then processed in two cases according to the format of the data:

  The first : Data is a single, pure label case, such as "<p></p>" or "<input/>" or "<input >", then assemble the array to return after creating the label

  // Rsingletag =/^< (\w+) \s*\/?> (?: <\/\1>|) $/

var parsed = rsingletag.exec (data);

if (parsed) {

return [context. CreateElement(parsed[1]);

}

  second : In other cases, use jquery.buildfragment to create a DOM node fragment (the DOM node that wraps data created) to assemble an array of returns. It is important to note that the keepscripts parameter specifies whether to retain the script tag, which defaults to false.

Scripts =!keepscripts && [];

  

parsed = JQuery. buildfragment ([data], context, scripts);

if (scripts) {
JQuery (Scripts). Remove ();
}
return Jquery.merge ([], parsed.childnodes);

Inside the jquery.buildfragment, this is the core of parsehtmL.

Creating a document Fragment Core function jquery.buildfragment (elems, context, scripts, selection)

  First, create a secure document fragmentation node

Safe = createsafefragment (context);

The so-called security, refers to is actually the low version of IE compatibility issues. The source code for the Createsafefragment function is as follows

function Createsafefragment (document) {

var list = Nodenames.split ("|"),

Safefrag = Document.createdocumentfragment (); ie6,7,8 Browser takes safefrage as HTMLDocument type

Add a hack to the HTML5 new tab in Ie6-8, what's the specific effect? I don't know, either.

if ( safefrag.createelement ) {

while (List.length) {

Safefrag.createelement (List.pop ());

}

}

return Safefrag;

}

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

It can be seen that if the browser supports safefrag.createelement (ie low version), is not supported Nodenames in the label, you need to use createelement to create each, Specific God horse role, please inform people informed, thank you .

As for the method of dynamically creating HTML nodes Document.createdocumentfragment, there are other relevant methods, interested children's shoes can check the information:

· Crateattribute (name): Create an attribute node with the name specified

· Createcomment (text): Create a comment node with text

· Createdocumentfragment (): Create a document fragmentation node

· CreateElement (tagname): Create a node with a label named TagName

· createTextNode (text): Creates a text node that contains textual text

 Then: Collect node elements

Traversing the Elems parameter, the node Elem generated for each element is pressed into the node cache nodes.

The treatment of each elem is divided into three different cases:

1) jquery.type (elem) = = = "Object"//Add node directly

Jquery.merge (nodes, Elem.nodetype?) [Elem]: Elem);

2)!rhtml.test (elem)//Non-"< ..." or "&...;" This type of HTML element is processed directly as a text node

Nodes.push (Context.createtextnode (elem));

3) string HTML; use innerHTML to add elem to the DIV tag under the document fragment node safe, and then use div.childnodes to press all child nodes into the node cache nodes. The principle is simple, but ... Compatibility is a big problem. There are several compatibility issues that need to be addressed.

  in the low version of IE, some tags must be included in some tags , such as "<thead>" tag must be in "<table>".

jquery deliberately saves all such cases in Wrapmap, wrapmap (nesting layer, start tag, terminating tag) Wrapmap = {

Option: [1, "<select multiple= ' multiple ' >", "</select>"],

Legend: [1, "<fieldset>", "</fieldset>"],

Area: [1, "<map>", "</map>"],

PARAM: [1, "<object>", "</object>"],

THEAD: [1, "<table>", "</table>"],

TR: [2, "<table><tbody>", "</tbody></table>"],

Col: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"],

TD: [3, "<table><tbody><tr>", "</tr></tbody></table>"],

IE6-8 cannot load a link, script, style, or any HTML5 (noscope) label unless it is included in a div that follows a non-disruptive character.

_default:jquery.support.htmlserialize? [0, "", ""]: [1, "x<div>", "</div>"]

}

Get Elem first to determine the first label name, if you can find the corresponding property in the Wrapmap, then use the outer label in the Wrapmap, such as elem= "<thead><tr></tr></thead > "After processing becomes lem=" <table><thead><tr></tr></thead></table> ". Processing the source code as follows

TMP = TMP | | Safe.appendchild (Context.createelement ("div"));

Rtagname:/< ([\w:]+)/; Get the label signature

Tag = (rtagname.exec (elem) | | ["", ""] ) [1].tolowercase (); /

Wrap = wrapmap[Tag] | | Wrapmap._default;

Rxhtmltag:/< (?! Area|br|col|embed|hr|img|input|link|meta|param) (([\w:]+) [^>]*] \/>/gi.

A closed method such as "<div#F/>" is misused for a label that is not a single, such as "Div", and is changed to "<div#F></div>"

tmp.innerhtml = Wrap[1] + elem.replace (rxhtmltag, "<$1></$2>") + wrap[2];

  

It is possible to create a document fragment, but we will not be able to include the outer wrapper we added when we take out the elem corresponding document. This part of the process we combine the source to see

Position TMP to the parent node of the true Elem content section, then use the tmp.childnodes directly to

j = wrap[0];
while (j--) {
TMP = Tmp.lastchild;
}


Rleadingwhitespace =/^\s+/
IE will delete the starting space in the text, such as $ ("<span></span>") on IE and $ ("<span></span>"), three spaces in front of the span are wiped out. To get it back.
if (!jquery.support.leadingwhitespace && rleadingwhitespace.test (elem)) {
Nodes.push (context. createTextNode(Rleadingwhitespace.exec (Elem) [0]);
}

IE automatically adds <tbody> tags when creating table fragments
if (!jquery.support.tbody) {

Rtbody =/<tbody/i; set Elem to <table...</table> To remove tbody from the back
Elem the outermost label is <table>, and <tbody> is added by IE itself
Elem = Tag = = = "Table" &&!rtbody.test (elem)?
Tmp.firstchild:
Elem is a bare <thead> or <tfoot>, and automatically adds <table> and <tbody>
WRAP[1] = = = "<table>" &&!rtbody.test (elem)?
Tmp:
0;

Remove <tbody>
j = Elem && elem.childNodes.length;
while (j--) {
if (Jquery.nodename ((tbody = Elem.childnodes[j]), "tbody") &&!tbody.childnodes.length) {
Elem.removechild( tbody );
}
}
}

Jquery.merge (nodes, tmp.childnodes);//Collection node

Recycle data Recovery initial value for future use

Tmp.textcontent = "";

Fix #12392 for Oldie
while (Tmp.firstchild) {
Tmp.removechild (Tmp.firstchild);
}

TMP = Safe.lastchild;

OK, to this, the collection node element completes. Do not forget to finally delete the div tag that you added to the document fragment node.

  Finally: Building fragmented documents

Traverse each element node into a fragmented document, Safe.appendchild (Elem)

while ((Elem = nodes[i++])) {

#4087-If the elements of the start and end points are the same, and this is the element, do nothing; used in DOM selection operations

If (Selection && Jquery.inarray (Elem, selection)!==-1) {
Continue
}

Contains = Jquery.contains (Elem.ownerdocument, elem);

Add a node to the document fragment and collect the script tag
TMP = GETALL ( safe.appendchild (elem), "script");

Save script Execution Record
if (contains) {
Setglobaleval (TMP);
}

Capture scripts and save scripts to scripts
if (scripts) {
j = 0;
while ((Elem = tmp[j + +)) {
Rscripttype =/^$|\/(?: JAVA|ECMA) script/i
if (rscripttype.test (Elem.type | | "" ) ) {
Scripts.push (Elem);
}
}
}
}

Return safe;//back

Jquery.parsejson (data): Converting a well-formed JSON string to its corresponding JavaScript object

The so-called "well-formed" requirement is that the specified string must conform to a strict JSON format , for example: attribute names must be double-quoted , string values must also be double-quoted . If you pass in a JSON string that is not well-formed, a JS exception will be thrown.

Feature comparison point list if you can use window. Json.parse to parse is used directly.

if (window. JSON && window. Json.parse) {return window. Json.parse (data); }

Otherwise, use the (new Function ("return" + Data) () to parse .

Return (New Function ("return" + data));

The complete source code is as follows:

Parsejson:function (data) {

if (window. JSON && window. Json.parse) {return window. Json.parse (data); }//try to use the browser's json.parse to parse

if (data = = = NULL) {return data;}

if (typeof data = = = "string") {

data = Jquery.trim (data);//turn-around trailing blanks (ie cannot handle him)

if (data) {

Make sure that data is in strict JSON format, from Http://json.org/json2.js to logical

Rvalidchars =/^[\],:{}\s]*$/,
Rvalidbraces =/(?: ^|:|,) (?: \ s*\[) +/g,
Rvalidescape =/\\ (?: ["\\\/bfnrt]|u[\da-fa-f]{4})/g,
Rvalidtokens =/"[^" \\\r\n]* "|true|false|null|-? (?:\ d+\.|) \d+ (?: [ee][+-]?\d+|) /g,

if (Rvalidchars.test (Data.replace (Rvalidescape, "@"). Replace (Rvalidtokens, "]"). Replace (rvalidbraces , "")) ) {

return (New Function ("return" + data));

}

}

}

Jquery.error ("Invalid JSON:" + data);

}

Jquery.parsexml (data): parsing a string into its corresponding XML document

The function uses the browser's built-in parsing function to create a valid XML document that can be passed into the jquery () function to create a typical jquery object to traverse or otherwise manipulate.

This is relatively simple, lazy directly attached source code:

Parsexml:function (data) {

var XML, TMP;
if (!data | | typeof data!== "string") {
return null;
}
try {
if (window. Domparser) {//Standard
TMP = new Domparser ();
XML = tmp.parsefromstring (data, "text/xml");
} else {//IE
XML = new ActiveXObject ("Microsoft.XMLDOM");
Xml.async = "false";
Xml.loadxml (data);
}
} catch (e) {
xml = undefined;
}
if (!xml | |!xml.documentelement | | xml.getelementsbytagname ("parsererror"). Length) {
Jquery.error ("Invalid XML:" + data);
}
return XML;
}

jQuery-1.9.1 Source Analysis Series (ii) jquery selector cont.

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.