Imitating jquey and creating several package nodes, we found that jquery is inefficient. Next time, he could say how much these methods can be improved. The principle is basically like this. If strings are input, convert them into an element node. However, this element node can also have many layers and put the elements to be wrapped in the innermost layer. There are several methods to convert a string into an element node. 1. createelement and IE can be created together with element attributes, but only one layer can be created. 2. innerhtml, but the original string needs to be processed. Both IE and FF have many unexpected default behaviors, so you can add more or less. 3. createcontextualfragment. Because opera has a strange behavior, you need to select and modify the position of the element. Tested by the Japanese, it is much more efficient and safer to convert strings into nodes than innerhtml. The stronger the character, the weaker the character. If you want to input an element node, You need to clone it or change it to wrapall. If it is a function, pass the current element in and use some of its attributes to create a package element.
The original experiment (here wrapouter is equivalent to jquery's wrap ):
var parsehtml = function (STR) {If (document. createRange) {var range = document. createRange () range. setstartafter (document. body) return range. createcontextualfragment (STR)} else {return document. createelement (STR) }}var wrapouter = function (target, HTML) {var wrap = parsehtml (HTML); target. parentnode. insertbefore (WRAP, target); target. previussibling. appendchild (target)}
<Br/> <! Doctype HTML> <br/> <HTML dir = "LTR" lang = "ZH-CN"> <br/> <pead> <br/> <meta charset = "UTF-8" /> <br/> <meta content = "Ie = 8" http-equiv = "X-UA-compatible"/> <br/> <style type = "text/CSS "> <br/>. wrapper {<br/> margin: 5px 5px 5px; <br/> padding: 5px 5px 5px 5px; <br/> background-color: # dfe8f6; <br/> border: 1px solid magenta; <br/>}< br/>. inner {<br/> margin: 1em; <br/> Height: 20px; <br/> Background: # a9ea00 <br/>}< br/>. border {<br/> border: 2px solid red; <br/>}< br/> </style> <br/> <title> parcel node by situ zhengmei </title> </P> <p> <SCRIPT type = "text/JavaScript"> </P> <p> window. onload = function () {<br/> var parsehtml = function (STR) {<br/> If (document. createRange) {</P> <p> var range = document. createRange () <br/> range. setstartafter (document. body) <br/> return range. createcontextualfragment (STR) <br/>} else {<br/> return document. createelement (STR) <br/>}< br/> var wrapouter = function (target, HTML) {<br/> var wrap = parsehtml (HTML ); <br/> target. parentnode. insertbefore (WRAP, target); </P> <p> target. previussibling. appendchild (target) <br/>}< br/> var A = document. getelementbyid ("target"); <br/> wrapouter (a, "<Div class = 'border'> </div> ") <br/>}</P> <p> </SCRIPT> <br/> </pead> <br/> <body id = "id10"> </P> <p> <Div class = "Container"> <br/> <Div class = "inner" id = "target"> target node </div> <br/> </ div> <br/> </body> <br/> </ptml> <br/>
RunCode
If something goes wrong with opera, change range. setstartafter (document. Body) to our target element. In addition, the method for inserting package elements is changed from insertbefore to replaceChild to improve efficiency.
VaR wrapouter = function (target, HTML) {var wrap = html if (object. prototype. tostring. call (HTML) = "[object string]") {If (document. createRange) {var range = document. createRange (); range. selectnodecontents (target); Wrap = range. createcontextualfragment (HTML ). firstchild;} else {wrap = document. createelement (STR) ;}} target. parentnode. replaceChild (WRAP, target); wrap. appendchild (target )}
<Br/> <! Doctype HTML> <br/> <HTML dir = "LTR" lang = "ZH-CN"> <br/> <pead> <br/> <meta charset = "UTF-8" /> <br/> <meta content = "Ie = 8" http-equiv = "X-UA-compatible"/> <br/> <style type = "text/CSS "> <br/>. wrapper {<br/> margin: 5px 5px 5px; <br/> padding: 5px 5px 5px 5px; <br/> background-color: # dfe8f6; <br/> border: 1px solid magenta; <br/>}< br/>. inner {<br/> margin: 1em; <br/> Height: 20px; <br/> Background: # a9ea00 <br/>}< br/>. border {<br/> border: 2px solid red; <br/>}< br/> </style> <br/> <title> parcel node by situ zhengmei </title> </P> <p> <SCRIPT type = "text/JavaScript"> </P> <p> window. onload = function () {<br/> var wrapouter = function (target, HTML) {<br/> var wrap = html <br/> If (object. prototype. tostring. call (HTML) = "[object string]") {<br/> If (document. createRange) {<br/> var range = document. createRange (); <br/> range. selectnodecontents (target); <br/> wrap = range. createcontextualfragment (HTML ). firstchild; <br/>}else {<br/> wrap = document. createelement (STR); <br/>}< br/> target. parentnode. replaceChild (WRAP, target); <br/> wrap. appendchild (target) <br/>}< br/> var A = document. getelementbyid ("target"); <br/> wrapouter (a, "<Div class = 'border'> </div> ") <br/>}</P> <p> </SCRIPT> <br/> </pead> <br/> <body id = "id10"> </P> <p> <Div class = "Container"> <br/> <Div class = "inner" id = "target"> target node </div> <br/> </ div> <br/> </body> <br/> </ptml> <br/>
run the Code
// Add a parent element (wrapped element) to each matching element. Wrap: function (HTML) {// html can be an element node, it can also be an HTML snippet VaR _ wrap = function (target, HTML) {var wrap; If (is (HTML, "string") {If (document. createRange) {var range = document. createRange (); range. selectnodecontents (target); Wrap = range. createcontextualfragment (HTML ). firstchild;} else {wrap = document. createelement (HTML) ;}} else if (HTML. nodetype) {wrap = html. clonenode (true)} target. parentnode. replaceChild (WRAP, target); wrap. appendchild (target)} If (is (HTML, "function") {return this. each (function (El, index) {_ wrap (El, HTML. call (El, index) ;};} return this. each (function (EL) {_wrap (El, HTML )});},
abstract the method for creating a package element:
VaR _ parsehtml = function (El, HTML) {var wrap = HTML; If (Doc. createRange) {var range = Doc. createRange (); range. selectnodecontents (EL); var wrap = range. createcontextualfragment (HTML ). firstchild; range. detach (); Return wrap;} else {return Dom. parsehtml (HTML) ;}}// Add a parent element (wrapped element) to each matching element. Wrap: function (HTML) {// html can be an element node, it can also be an HTML snippet VaR _ wrap = function (target, HTML) {var wrap = HTML; If (! Wrap. nodetype) {wrap = Dom. _ parsehtml (target, HTML);} else {wrap = html. clonenode (true)} target. parentnode. replaceChild (WRAP, target); wrap. insertbefore (target, null)} If (is (HTML, "function") {return this. each (function (El, index) {_ wrap (El, HTML. call (El, index) ;};} return this. each (function (EL) {_ wrap (El, HTML)}) ;}, wrapinner: function (HTML) {VaR _ wrap = function (target, HTML) {var wrap = HTML; if (! Wrap. nodetype) {wrap = Dom. _ parsehtml (target, HTML);} else {wrap = html. clonenode (true)} target. insertbefore (WRAP, target. firstchild); For (VAR I = 1, n = target. childnodes. length; I <n; I ++) {wrap. appendchild (target. childnodes [I], null) }}if (is (HTML, "function") {return this. each (function (El, index) {_ wrap (El, HTML. call (El, index) ;};} return this. each (function (EL) {_ wrap (El, HTML)}) ;}, // wrap all matching elements with a tag/ /Practice: Add a parent element (Package) to the first matching element, and transfer all other matching elements to the parent element. // wrapall (HTML) wrapall (ELEM) wrapall: function (HTML) {var wrap = HTML; If (! Wrap. nodetype) wrap = Dom. _ parsehtml (this [0], HTML); this [0]. parentnode. replaceChild (WRAP, this [0]); return this. each (function (EL) {wrap. insertbefore (El, null );});},
Go To The jquery official website and check that the method of its package node has been upgraded. Many layers can be wrapped at a time, and I can only package one layer at a time. So I decided to call my original parsehtml method. See here.
VaR wrap = function (HTML) {// html can be an element node or an HTML part VaR _ wrap = function (target, HTML) {var wrap = HTML; If (! Wrap. nodetype) {If (Doc. createRange) {var range = Doc. createRange (); range. selectnodecontents (target); Wrap = range. createcontextualfragment (HTML ). firstchild;} else {wrap = Dom. parsehtml (HTML, null, true ). firstchild} else {wrap = html. clonenode (true)} target. parentnode. replaceChild (WRAP, target); While (wrap. firstchild & wrap. firstchild. nodetype = 1) {wrap = wrap. firstchild;} wrap. insertbefore (Target, null)} If (is (HTML, "function") {return this. each (function (El, index) {_ wrap (El, HTML. call (El, index) ;};} return this. each (function (EL) {_ wrap (El, HTML)});} // wrap each child node that matches the element with something. var wrapinner = function (HTML) {VaR _ wrap = function (target, HTML) {var wrap = HTML; If (! Wrap. nodetype) {wrap = Dom. parsehtml (HTML, null, true ). firstchild} else {wrap = html. clonenode (true)} target. insertbefore (WRAP, target. firstchild); While (wrap. firstchild & wrap. firstchild. nodetype = 1) {wrap = wrap. firstchild;} For (VAR I = 1, n = target. childnodes. length; I <n; I ++) {wrap. appendchild (target. childnodes [I], null) }}if (is (HTML, "function") {return this. each (function (El, index) {_ wrap (El, HTML. call (El, index) ;};} return this. each (function (EL) {_ wrap (El, HTML)});} // wrap all matching elements with one tag // practice: add a parent element (Package) to the First Matching Element and transfer all other matching elements to this parent element. // wrapall (HTML) wrapall (ELEM) vaR wrapall = function (HTML) {var wrap = HTML; If (! Wrap. nodetype) {If (Doc. createRange) {var range = Doc. createRange (); range. selectnodecontents (this [0]); Wrap = range. createcontextualfragment (HTML ). firstchild;} else {wrap = Dom. parsehtml (HTML, null, true ). firstchild} else {wrap = html. clonenode (true)} This [0]. parentnode. replaceChild (WRAP, this [0]); While (wrap. firstchild & wrap. firstchild. nodetype = 1) {wrap = wrap. firstchild;} return this. each (function (EL) {wrap. insertbefore (El, null );});}
I found that there are a lot of repeated code. I can abstract it again. For outsiders, jquery is also difficult to understand.
Dom. Mixin (DOM [FN], (function () {var wraphelper = function (target, HTML) {var wrap = HTML; If (! Wrap. nodetype) {If (document. createRange) {var rangew.dom.doc. createRange (); range. selectnodecontents (target); Wrap = range. createcontextualfragment (HTML ). firstchild;} else {wrap = Dom. parsehtml (HTML, null, true ). firstchild} else {wrap = html. clonenode (true)} var insertor = wrap; while (insertor. firstchild & insertor. firstchild. nodetype = 1) {insertor = insertor. firstchild;} return [wrap, insertor]} // wrap all matching elements with a tag // method: Add a parent element (Package) to the First Matching Element ), then transfer all other matching elements to this parent element. // wrapall (HTML) wrapall (ELEM) var wrapall = function (HTML) {If (Dom. isfunction (HTML) {return this. each (function (El, index) {dom (this ). wrapall (HTML. call (this, index) ;};}var arr = wraphelper (this [0], HTML); var wrap = arr [0], insertor = arr [1]; this [0]. parentnode. replaceChild (WRAP, this [0]); return this. each (function (EL) {insertor. insertbefore (El, null) ;}) ;}// Add a parent element (wrapped element) to each matching element, VAR wrap = function (HTML) {return this. each (function () {dom (this ). wrapall (HTML) ;};}// wrap each child node that matches the element with something. var wrapinner = function (HTML) {VaR _ wrap = function (target, HTML) {var arr = wraphelper (target, HTML); var wrap = arr [0], insertor = arr [1]; target. insertbefore (WRAP, target. firstchild); For (VAR I = 1, n = target. childnodes. length; I <n; I ++) {insertor. appendchild (target. childnodes [I], null) }}if (is (HTML, "function") {return this. each (function (El, index) {_ wrap (El, HTML. call (El, index) ;};} return this. each (function (EL) {_ wrap (El, HTML)});} return {wrapall: wrapall, wrap: Wrap, wrapinner: wrapinner }})());
the unwrap method will be used later!