function findDelegateTarget(event, selector) { let currentNode = event.target; while (currentNode) { if (currentNode.matches(selector)) { return currentNode; } if (currentNode == event.currentTarget) { break; } currentNode = currentNode.parentElement; } return null; } // delegate(table, 'th', click, handler) // table // thead // th ^* // code <-- function delegate(topElement, selector, eventName, handler, context) { /* jshint -W040 */ topElement.addEventListener(eventName, function(event) { let found = findDelegateTarget(event, selector); // .currentTarget is read only, I can not overwrite it to the "found" element // Object.create wrapper would break event.preventDefault() // so, keep in mind: // --> event.currentTarget is always the top-level (delegating) element! // use "this" to get the found target event.delegateTarget = found; // use instead of "this" in object methods if (found) { // if in context of object, use object as this, handler.call(context || this, event); } }); } delegate.delegateMixin = function(obj) { obj.delegate = function(selector, eventName, handler) { delegate(this.elem, selector, eventName, handler, this); }; }; module.exports = delegate;