We designed an event proxy function in a sterile environment last time, but the performance is a problem. To solve this problem, we need to cache the node set and find that the node set is insufficient to cope with new situations, replace the node set and start matching again. The following is a new solution:
var delegate = function(selector,type,callback){ var els = $(selector); addEvent(document,type,function(e){ var flag = true; var node = e.srcElement || e.target; for(var i=0,el;el = els[i++];){ if(node === el){ flag = false; return callback.call(node,e); } } if(flag){ els = $(selector); for(var i=0,el;el = els[i++];){ if(node === el){ return callback.call(node,e); } } } },true); }
<Br/> <! Doctype HTML> <br/> <HTML lang = "ZH-ch" id = "html"> <br/> <pead> <br/> <meta charset = "UTF-8" /> <br/> <meta content = "Ie = 8" http-equiv = "X-UA-compatible"/> <br/> <title> event proxy by situ zhengmei </title> </P> <p> <SCRIPT type = "text/JavaScript"> <br/> window. onload = function () {<br/> var addevent = function (El, type, callback, data) {<br/> If (El. addeventlistener) {// If the custom object is used, the callback function is bound. <br/> el. addeventlistener (type, callb Ack ,!! Data); <br/>} else if (El. attachevent) {<br/> el. attachevent ("On" + type, function () {<br/> return callback. call (El, window. event) <br/>}); <br/>}< br/> var delegate = function (selector, type, callback) {<br/> var els =$ (selector); <br/> addevent (document, type, function (e) {<br/> var flag = true; <br/> var node = E. srcelement | e.tar get; <br/> for (VAR I = 0, El; El = els [I ++];) {<br/> If (Node = El) {<br/> flag = false; <br/> return callback. call (node, e); <br/>}< br/> If (FLAG) {<br/> els =$ (selector ); <br/> for (VAR I = 0, El; El = els [I ++];) {<br/> If (node = El) {<br/> return callback. call (node, e); <br/>}< br/>}, true ); <br/>}< br/> delegate ("# list li", "click", function (e) {<br/> alert (this. innerhtml + E. type) <br/>}); <br/>}< br/> var $ = function (select Or, context) {<br/> context = context | document <br/> try {<br/> var els = context. queryselectorall (selector), <br/> result = [], rI = 0, I = 0, n = els. length; <br/> for (; I <n; I ++) {<br/> result [ri ++] = els [I] <br/>}< br/> return result; <br/>} catch (E) {<br/> alert ("your browser does not support queryselectorall") <br/>}< br/> var AAA = function () {<br/> var li = document. createelement ("Li"); <br/> Li. innerhtml = "dynamic Add "+ AAA. AA ++ <br/> $ ("# List") [0]. appendchild (LI) <br/>}< br/> AAA. AA = 0; <br/> </SCRIPT> </P> <p> </pead> <br/> <body id = "body"> <br/> <p> situ zhengmei: event proxy </p> <br/> <ul id = "list"> <br/> <li> unordered list 1 </LI> <br/> <li> unordered list 2 </LI> <br/> <li> unordered list 3 </LI> <br/> <li> unordered list 4 </LI> <br/> </ ul> <br/> <p> the unordered list below has no ID! </P> <br/> <ul> <br/> <li> unordered list 1 </LI> <br/> <li> unordered list 2 </LI> <br/> <li> unordered list 3 </LI> <br/> <li> unordered list 4 </LI> <br/> </ul> <br/> <button type = "button" onclick = "AAA () "> dynamic addition </button> </P> <p> </body> <br/> </ptml> <br/>
Run code
Now let's consider another situation. Previously, we used the comparison of all equals, but what if the event source is a more underlying element? In other words, it is the following situation.
<div onclick="alert('outer')" id="outer"> <div onclick="alert('middle')" id="middle"> <div onclick="alert('inner')" id="inner"></div> </div> </div>
When we click the inner element, The onclick of the middle and outer above is also triggered. Therefore, we must introduce the include criterion. Here I will give the answer directly. For more information, see my blog post.
var contains = function(el, root) { if (el.compareDocumentPosition) return (el.compareDocumentPosition(root) & 8) === 8; if (root.contains && el.nodeType === 1){ return root.contains(el) && root !== el; } while ((el = el.parentNode)) if (el === root) return true; return false; } var delegate = function(selector,type,callback){ var els = $(selector); addEvent(document,type,function(e){ var flag = true; var src = e.srcElement || e.target; for(var i=0,el;el = els[i++];){ if(el === src || contains(src,el) ){ flag = false; return callback.call(el,e); } } if(flag){ els = $(selector); for(var i=0,el;el = els[i++];){ if(el === src || contains(src,el) ){ return callback.call(el,e); } } } },true); }
<Br/> <! Doctype HTML> <br/> <HTML lang = "ZH-ch" id = "html"> <br/> <pead> <br/> <meta charset = "UTF-8" /> <br/> <meta content = "Ie = 8" http-equiv = "X-UA-compatible"/> <br/> <title> event proxy by situ zhengmei </title> </P> <p> <SCRIPT type = "text/JavaScript"> <br/> window. onload = function () {<br/> var addevent = function (El, type, callback, data) {<br/> If (El. addeventlistener) {// If the custom object is used, the callback function is bound. <br/> el. addeventlistener (type, callb Ack ,!! Data); <br/>} else if (El. attachevent) {<br/> el. attachevent ("On" + type, function () {<br/> return callback. call (El, window. event) <br/>}); <br/>}< br/> var delegate = function (selector, type, callback) {<br/> var els =$ (selector); <br/> addevent (document, type, function (e) {<br/> var flag = true; <br/> var src = E. srcelement | e.tar get; <br/> for (VAR I = 0, El; El = els [I ++];) {<br/> If (E L === SRC | contains (SRC, El) {<br/> flag = false; <br/> return callback. call (El, e); <br/>}< br/> If (FLAG) {<br/> els =$ (selector ); <br/> for (VAR I = 0, El; El = els [I ++];) {<br/> If (El = SRC | contains (SRC, El) {<br/> return callback. call (El, e); <br/>}< br/>}, true ); <br/>}< br/> delegate ("# list li", "click", function (e) {<br/> alert (this. innerhtml + E. type) <br/>}); <br />}< Br/> var $ = function (selector, context) {<br/> context = context | document <br/> try {<br/> var els = context. queryselectorall (selector), <br/> result = [], rI = 0, I = 0, n = els. length; <br/> for (; I <n; I ++) {<br/> result [ri ++] = els [I] <br/>}< br/> return result; <br/>} catch (E) {<br/> alert ("queryselectorall is not supported by your browser") <br/>}< br/> var contains = function (El, root) {<br/> If (El. COMPAR Edocumentposition) <br/> return (El. comparedocumentposition (Root) & 8) ===8; <br/> If (root. contains & el. nodetype = 1) {<br/> return root. contains (EL) & root! = El; <br/>}< br/> while (El = el. parentnode) <br/> If (El = root) return true; <br/> return false; <br/>}< br/> var AAA = function () {<br/> var li = document. createelement ("Li"); <br/> Li. innerhtml = "dynamic addition" + AAA. AA ++ <br/> $ ("# List") [0]. appendchild (LI) <br/>}< br/> AAA. AA = 0; <br/> </SCRIPT> <br/> <style type = "text/CSS"> <br/> # Inner {<br/> padding: 10px; <br/> width: 50px; <br/> Height: 50px; <Br/> Background: #4dc2f2; <br/>}< br/># middle {<br/> padding: 10px; <br/> width: 100px; <br/> Height: 100px; <br/> Background: # ff98ed; <br/>}< br/> # outer {<br/> padding: 10px; <br/> width: 150px; <br/> Height: 150px; <br/> background: #00ff00 <br/>}< br/> </style> <br/> </pead> <br/> <body id = "body"> <br/> <p> situ zhengmei: event proxy </p> <br/> <ul id = "list"> <br/> <li> unordered list 1 </LI> <br/> <li> unordered list 2 </LI> <br/> <li> Unordered list 3 </LI> <br/> <li> unordered list 4 </LI> <br/> </ul> <br/> <p> unordered list there is no ID! </P> <br/> <ul> <br/> <li> unordered list 1 </LI> <br/> <li> unordered list 2 </LI> <br/> <li> unordered list 3 </LI> <br/> <li> unordered list 4 </LI> <br/> </ul> <br/> <button type = "button" onclick = "AAA () "> dynamic addition </button> <br/> <Div onclick =" alert ('outer ') "id =" outer "> <br/> <Div onclick =" alert ('middle ') "id =" Middle "> <br/> <Div onclick =" alert ('inner ') "id =" inner "> </div> <br/> </body> <br/> </ptml> <br/>
Run code
We then separate the logic of filtering event sources into the following. It's time to consider connecting the first part of the Event System!
var handle = function(e,obj){ var flag = true, src = e.srcElement || e.target, els = obj.nodes; for(var i=0,el;el = els[i++];){ if(el === src || contains(src,el) ){ flag = false; return obj.callback.call(el,e); } } if(flag){ els = obj.nodes = $(obj.selector); for(var i=0,el;el = els[i++];){ if(el === src || contains(src,el) ){ return obj.callback.call(el,e); } } } } var delegate = function(selector,type,callback){ var handleObj = {}; handleObj.callback = callback; handleObj.selector = selector; handleObj.nodes = $(selector); addEvent(document,type,function(e){ handle(e,handleObj) },true); }