Skip to content

Instantly share code, notes, and snippets.

@termi
Created April 12, 2012 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save termi/2369790 to your computer and use it in GitHub Desktop.
Save termi/2369790 to your computer and use it in GitHub Desktop.
event delegation. It is nearly 140 bytes but unsafe. For more complex solution see comments
function(
a, //CSS selector
b //callback function
) {
return function(
e, // event
c, // (placeholder)
d // (placeholder)
) {
d = e.target;
do d.matchesSelector(a) && //Match current node | alternative: match(d, a)
(c = b.call(d, e)) // executes callback | "this" is maches node
while (
c !== !1 && // if callback return false, stop bubbling
d != this && // stop element
(d = d.parentNode)
);
return c // return result from last callback execution
}
};
<html>
<style>
div {
height: 40px;
margin: 40px 0;
background-color: red;
}
div.A {
background-color: green;
}
</style>
<c id=test>
<div class=A>s</div>
<br>
<div class=B>s</div>
<br>
<div class="A C">s</div>
</c>
<script>
if(!Element.prototype.matchesSelector) {
Element.prototype.matchesSelector =
Element.prototype.webkitMatchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector || function(selector) {
if(!selector)return false;
if(selector === "*")return true;
var thisObj = this,
parent,
i,
str,
tmp,
match = false;
if(/^[\w#\.][\w-]*$/.test(selector) || /^(\.[\w-]*)+$/.test(selector)) {
switch (selector.charAt(0)) {
case '#':
return thisObj.id === selector.slice(1);
break;
case '.':
match = true;
i = -1;
tmp = selector.slice(1).split(".");
str = " " + thisObj.className + " ";
while(tmp[++i] && match) {
match = !!~str.indexOf(" " + tmp[i] + " ");
}
return match;
break;
default:
return thisObj.tagName && thisObj.tagName.toUpperCase() === selector.toUpperCase();
}
}
parent = thisObj.parentNode;
if(parent && parent.querySelector) {
match = parent.querySelector(selector) === thisObj;
}
if(!match && (parent = thisObj.ownerDocument)) {
tmp = parent.querySelectorAll(selector);
for (i in tmp ) if(_hasOwnProperty(tmp, i)) {
match = tmp[i] === thisObj;
if(match)return true;
}
}
return match;
}
}
function delegate(a,b){return function(e,c,d){d=e.target;do d.matchesSelector(a)&&(c=b.call(d,e));while(c!==!1&&d!=this&&(d=d.parentNode));return c}};
test.addEventListener("click", delegate(".A", function(e){console.log(e)}))
</script>
function(a,b){return function(e,c,d){d=e.target;do d.matchesSelector(a)&&(c=b.call(d,e));while(c!==!1&&d!=this&&(d=d.parentNode));return c}};
{
"name": "delegate",
"keywords": ["delegate", "events", "event", "DOM"]
}
@Raynos
Copy link

Raynos commented Apr 12, 2012

That's not how you write readable code :P

@termi
Copy link
Author

termi commented Apr 13, 2012

Posted more complex, readable and error-proof version with 3 different match filters and handleEvent support

@Raynos
Copy link

Raynos commented Apr 13, 2012

If you don't turn this into a little library, I will :D

@termi
Copy link
Author

termi commented Apr 14, 2012

More complex and error-proof version is now https://github.com/termi/DelegateListener

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment