Skip to content

Instantly share code, notes, and snippets.

@softwarespot
Last active July 2, 2017 13:55
Show Gist options
  • Save softwarespot/cfadec50eeac8ec4c636ad134379af39 to your computer and use it in GitHub Desktop.
Save softwarespot/cfadec50eeac8ec4c636ad134379af39 to your computer and use it in GitHub Desktop.
Event delegation
var on = _createEvent.bind(null, 'on');
var remove = on(document, 'click', 'body', function (event, target) {
// "this" is set to the target element node
console.log('On::', this, event, target);
});
var once = _createEvent.bind(null, 'once');
once(document, 'click', 'body', function (event, target) {
// "this" is set to the target element node
console.log('Once::', this, event, target);
});
// Wrapper for creating an event function by type
function _createEvent(type, el, eventName, selector, fn) {
if (typeof selector === 'function') {
// The following order should be maintained as is
fn = selector;
selector = undefined;
}
el.addEventListener(eventName, _onEvent, false);
// Return the function to remove the attached event
return _removeEvent;
// On event dispatch, invoke the callback function (includes event delegation support)
function _onEvent(event) {
if (!selector) {
_removeEvent(true);
return fn.call(el, event, el);
}
// Should use Array.from() in ES2015
var els = Array.prototype.slice.call(document.querySelectorAll(selector));
var target = event.target;
while (target && el !== target && target.nodeType !== Node.DOCUMENT_NODE) {
// Should use Array.prototype.includes() in ES2015
if (els.indexOf(target) !== -1) {
_removeEvent(true);
return fn.call(target, event, target);
}
target = target.parentNode;
}
}
// Cancel the node's event listener (used internally and externally)
function _removeEvent(/* internalRemoval */) {
if (arguments[0] !== true || type === 'once') {
el.removeEventListener(eventName, _onEvent, false);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment