How JavaScript implements its own DOM selector principle and code

Source: Internet
Author: User

Interpreter mode (Interpreter): defines a syntax format, implements it through program interpretation and completes the corresponding task. In front-end programming scenarios, you can apply the interpreter mode to interpret the CSS selector for DOM element selection.

Open and closed Principle: The open and closed principle in object-oriented systems is that classes or modules should be open to modify and close extensions. In this dom selector, id selector, element selector, and class selector are implemented, if you need an attribute selector later, define an attribute selector to implement the corresponding method, and add the corresponding branch of the property selector object in a simple factory.

Matching Principle: The browser matches the CSS selector from right to left, so the matching behavior should be consistent with that of the browser native when implementing its own DOM selector.

Code:Copy codeThe Code is as follows: (function (ns ){
/*
// TagName
Console. log (dom. get ("p "));
// # Id
Console. log (dom. get ("# div "));
//. Class
Console. log (dom. get (". span", document. body ));
// Tag. class
Console. log (dom. get ("div. span "));
// # Id. class
Console. log (dom. get ("# div. span "));
//. Class. class
Console. log (dom. get (". ul. li-test "));
*/
Var doc = document;
Var simple =/^ (? : # | \.)? ([\ W-_] + )/;
Function api (query, context ){
Context = context | doc;
// Call the native Selector
If (! Simple. test (query) & context. querySelectorAll ){
Return context. querySelectorAll (query );
} Else {
// Call the custom Selector
Return interpret (query, context );
}
}
// Explain the execution dom selector.
Function interpret (query, context ){
Var parts = query. replace (/\ s +/, ""). split ("");
Var part = parts. pop ();
Var selector = Factory. create (part );
Var ret = selector. find (context );
Return (parts [0] & ret [0])? Filter (parts, ret): ret;
}
// ID Selector
Function IDSelector (id ){
This. id = id. substring (1 );
}
IDSelector. prototype = {
Find: function (context ){
Return document. getElementById (this. id );
},
Match: function (element ){
Return element. id = this. id;
}
};
IDSelector. test = function (selector ){
Var regex =/^ # ([\ w \-_] + )/;
Return regex. test (selector );
};
// Element Selector
Function TagSelector (tagName ){
This. tagName = tagName. toUpperCase ();
}
TagSelector. prototype = {
Find: function (context ){
Return context. getElementsByTagName (this. tagName );
},
Match: function (element ){
Return this. tagName = element. tagName. toUpperCase () | this. tagName = "*";
}
};
TagSelector. test = function (selector ){
Var regex =/^ ([\ w \ * \-_] + )/;
Return regex. test (selector );
};
// Class selector
Function ClassSelector (className ){
Var splits = className. split ('.');
This. tagName = splits [0] | undefined;
This. className = splits [1];
}
ClassSelector. prototype = {
Find: function (context ){
Var elements;
Var ret = [];
Var tagName = this. tagName;
Var className = this. className;
Var selector = new TagSelector (tagName | "*"));
// Supports native getElementsByClassName
If (context. getElementsByClassName ){
Elements = context. getElementsByClassName (className );
If (! TagName ){
Return elements;
}
For (var I = 0, n = elements. length; I <n; I ++ ){
If (selector. match (elements [I]) {
Ret. push (elements [I]);
}
}
} Else {
Elements = selector. find (context );
For (var I = 0, n = elements. length; I <n; I ++ ){
If (this. match (elements [I]) {
Ret. push (elements [I]);
}
}
}
Return ret;
},
Match: function (element ){
Var className = this. className;
Var regex = new RegExp ("^ | \ s" + className + "$ | \ s ");
Return regex. test (element. className );
}
};
ClassSelector. test = function (selector ){
Var regex =/^ ([\ w \-_] + )? \. ([\ W \-_] + )/;
Return regex. test (selector );
};
// TODO: attribute Selector
Function AttributeSelector (attr ){
This. find = function (context ){
};
This. match = function (element ){
};
}
AttributeSelector. test = function (selector ){
Var regex =/\ [([\ w \-_] + )(? : = ([\ W \-_] + ))? \]/;
Return regex. test (selector );
};
// Filter by parent Element
Function filter (parts, nodeList ){
Var part = parts. pop ();
Var selector = Factory. create (part );
Var ret = [];
Var parent;
For (var I = 0, n = nodeList. length; I <n; I ++ ){
Parent = nodeList [I]. parentNode;
While (parent & parent! = Doc ){
If (selector. match (parent )){
Ret. push (nodeList [I]);
Break;
}
Parent = parent. parentNode;
}
}
Return parts [0] & ret [0]? Filter (parts, ret): ret;
}
// Create a selector object based on the query selector.
Var Factory = {
Create: function (query ){
If (IDSelector. test (query )){
Return new IDSelector (query );
} Else if (ClassSelector. test (query )){
Return new ClassSelector (query );
} Else {
Return new TagSelector (query );
}
}
};
Ns. dom | (ns. dom = {});
Ns. dom. get = api;
} (This ));

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.