Skip to content

Instantly share code, notes, and snippets.

@w3core
Last active December 29, 2016 10:40
Show Gist options
  • Save w3core/d4d59fcee33ac03faace568318fbdfbc to your computer and use it in GitHub Desktop.
Save w3core/d4d59fcee33ac03faace568318fbdfbc to your computer and use it in GitHub Desktop.
"selector".on (events, listener, closest)
/**
* on v.1.0.0
* ==========
* This tiny extension allows to process events from elements that are added to the document at a later time.
* By picking an element that is guaranteed to be present at the time the delegated event handler is attached,
* you can use delegated events to avoid the need to frequently attach and remove event handlers.
* It's safe to attach events without waiting for the document to be ready.
*
* "selector".on (events, listener, closest)
*
* @param selector (String) A comma separated list of CSS selectors
* @param events (String) A comma or space separated list of events that should be handled by listener
* @param listener (Function) Listener function
* @param closest (Boolean) Optional. To handle events if any children node dispatched
*
* @returns (Function) Listener destructor
*
* @license MIT
* @author Max Chuhryaev
*/
!new function (win, doc) {
var FUNCTION = "function", BLUR = "blur";
String.prototype.on = function on (event, handler, closest) {
var that = this, event = event.match(/[^,\s]+/g) || [], offBlur = onBlur.call(that, event, handler, closest);
var on = function (e) {
var node = e.target;
if (typeof handler == FUNCTION && matchesSelector(node, that, closest)) return handler.call(that, e);
};
listen(!0, event, win, on);
return function off () {
if (typeof offBlur == FUNCTION) offBlur();
listen(!1, event, win, on);
};
}
function onBlur (event, handler, closest) {
var that = this, idx = event.indexOf(BLUR), destruct = [], events = "click keyup";
if (idx >= 0 && typeof handler == FUNCTION) {
event.splice(idx, 1);
var on = function (e) {
var node = e.target;
if (!node._hasBlurHandler && matchesSelector(node, that, closest)) {
node._hasBlurHandler = !0;
listen(!0, BLUR, node, handler);
destruct.push(function(){
delete node._hasBlurHandler;
listen(!1, BLUR, node, handler);
});
}
};
listen(!0, events, win, on);
return function () {
listen(!1, events, win, on);
for (var i in destruct) destruct[i]();
};
}
}
function listen (add, event, node, handler) {
var pfx = "EventListener", event = typeof event == "string" ? event.match(/[^,\s]+/g) || [] : event;
var fn = (add ? "add" : "remove") + pfx;
for (var i in event) node[fn](event[i], handler, !1);
}
function _matchesSelector(el, selector) {
if (el == win || el == doc) return !1;
var p = Element.prototype;
var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
return [].indexOf.call(doc.querySelectorAll(s), this) !== -1;
};
return f.call(el, selector);
}
function matchesSelector (el, selector, closest) {
if (_matchesSelector(el, selector)) return !0;
if (!closest) return !1;
return el.parentNode ? matchesSelector (el.parentNode, selector, closest) : !1;
}
}(window, document);
!new function(h,l){function n(a,b,d){var e=this,c=a.indexOf("blur"),f=[];if(0<=c&&"function"==typeof b){a.splice(c,1);var m=function(a){var c=a.target;!c._hasBlurHandler&&k(c,e,d)&&(c._hasBlurHandler=!0,g(!0,"blur",c,b),f.push(function(){delete c._hasBlurHandler;g(!1,"blur",c,b)}))};g(!0,"click keyup",h,m);return function(){g(!1,"click keyup",h,m);for(var a in f)f[a]()}}}function g(a,b,d,e){b="string"==typeof b?b.match(/[^,\s]+/g)||[]:b;a=(a?"add":"remove")+"EventListener";for(var c in b)d[a](b[c],e,!1)}function p(a,b){if(a==h||a==l)return!1;var d=Element.prototype;return(d.matches||d.webkitMatchesSelector||d.mozMatchesSelector||d.msMatchesSelector||function(a){return-1!==[].indexOf.call(l.querySelectorAll(a),this)}).call(a,b)}function k(a,b,d){return p(a,b)?!0:d?a.parentNode?k(a.parentNode,b,d):!1:!1}String.prototype.on=function(a,b,d){var e=this;a=a.match(/[^,\s]+/g)||[];var c=n.call(e,a,b,d),f=function(a){var c=a.target;if("function"==typeof b&&k(c,e,d))return b.call(e,a)};g(!0,a,h,f);return function(){"function"==typeof c&&c();g(!1,a,h,f)}}}(window,document);
@w3core
Copy link
Author

w3core commented Dec 26, 2016

on v.1.0.0

This tiny extension allows to process events from elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. It's safe to attach events without waiting for the document to be ready.

"selector".on (events, listener, closest) // @returns (Function) Listener destructor
Parameter Type Description
selector [required] String A comma separated list of CSS selectors
events [required] String A comma or space separated list of events that should be handled by listener
listener [required] Function Listener function
closest [optional] Boolean To handle events if any children node dispatched

Usage example

var listener = function(e){
  console.log(e.type, e.target);
};
var off = "button, input, textarea".on("focus blur input", listener);
// Call off(); to remove event listener

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