├── .gitignore ├── package.json ├── README.md ├── lib ├── utils.js └── index.js ├── .eslintrc └── dist ├── bundle.min.js └── bundle.js /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node ### 2 | # Logs 3 | logs 4 | *.log 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Dependency directory 12 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 13 | node_modules 14 | 15 | .DS_Store -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tye", 3 | "description": "Micro event delegation module", 4 | "version": "1.0.0", 5 | "author": "David Chase ", 6 | "bugs": { 7 | "url": "https://github.com/davidchase/tye/issues" 8 | }, 9 | "homepage": "https://github.com/davidchase/tye", 10 | "keywords": [ 11 | "delegation", 12 | "dom", 13 | "events" 14 | ], 15 | "license": "MIT", 16 | "main": "lib/index.js", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/davidchase/tye.git" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tye 2 | Micro Event Delegation Module 3 | 4 | 5 | ### Usage 6 | ```js 7 | // Using browserify 8 | var tye = require('tye'); 9 | // or using the bundled file in dist bundled in UMD format 10 | 11 | 12 | // Bind click event to document.body 13 | tye(document.body).on('click', someFunction); 14 | // Event Delegation: 15 | tye(document.body).on('click', '.my-class', someFunction); 16 | 17 | // Remove click binding from '.my-class' 18 | tye(document.body).off('click', '.my-class'); 19 | // Remove all click bindings from document.body 20 | tye(document.body).off('click'); 21 | ``` 22 | 23 | ### Under the Hood 24 | This is a wrapper around [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) 25 | 26 | That allows for event delegation by using [element.matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) 27 | 28 | Thats it, very simple implementation. **2kb** minified 29 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | exports.partial = function partial(fn) { 3 | var args = Array.apply(null, arguments).slice(1); 4 | return function() { 5 | var lastArgs = Array.apply(null, arguments); 6 | return fn.apply(this, args.concat(lastArgs)); 7 | }; 8 | }; 9 | 10 | exports.partialR = function partialR(fn) { 11 | var args = Array.apply(null, arguments).slice(1); 12 | return function() { 13 | var firstArgs = Array.apply(null, arguments); 14 | return fn.apply(this, firstArgs.concat(args)); 15 | }; 16 | }; 17 | 18 | exports.matches = function elementMatches(element, selector) { 19 | var ElementProto = Element.prototype; 20 | var func = ElementProto.matches || 21 | ElementProto.webkitMatchesSelector || 22 | ElementProto.mozMatchesSelector || 23 | ElementProto.msMatchesSelector || 24 | function fallbackElementMatches(selektor) { 25 | return Array.apply(null, document.querySelectorAll(selektor)).indexOf(this) !== -1; 26 | }; 27 | return func.call(element, selector); 28 | }; -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var matches = require('./utils').matches; 3 | var partial = require('./utils').partial; 4 | var partialR = require('./utils').partialR; 5 | var internals = {}; 6 | 7 | internals.refs = {}; 8 | internals.updateRefs = function updateRefs(delegator, type, fn, selector) { 9 | internals.refs[delegator] = internals.refs[delegator] || {}; 10 | internals.refs[delegator][type] = internals.refs[delegator][type] || {}; 11 | internals.refs[delegator][type][selector] = internals.refs[delegator][type][selector] || []; 12 | return internals.refs[delegator][type][selector].push(fn); 13 | }; 14 | internals.classFn = function classFn(e, selector, fn) { 15 | if (!matches(e.target, selector)) { 16 | return undefined; 17 | } 18 | return fn && fn.call(fn, e); 19 | }; 20 | internals.addListener = function addListener(delegator, type, fn, selector) { 21 | internals.updateRefs(delegator, type, fn, selector); 22 | delegator.addEventListener(type, fn); 23 | }; 24 | internals.removeListener = function removeListener(type, delegator, fn) { 25 | delegator.removeEventListener(type, fn); 26 | }; 27 | internals.turnOn = function turnOn(delegator, type, selector, fn) { 28 | if (typeof selector === 'function') { 29 | return internals.addListener(delegator, type, selector); 30 | } 31 | return internals.addListener(delegator, type, partialR(internals.classFn, selector, fn), selector); 32 | }; 33 | internals.turnOff = function turnOff(delegator, type, selector) { 34 | if (selector && selector in internals.refs[delegator][type]) { 35 | return internals.refs[delegator][type][selector].forEach(partial(internals.removeListener, type, delegator)); 36 | } 37 | Object.keys(internals.refs[delegator][type]).forEach(function(key) { 38 | internals.refs[delegator][type][key].forEach(partial(internals.removeListener, type, delegator)); 39 | }); 40 | }; 41 | module.exports = function tye(delegator) { 42 | return { 43 | on: function on(type, selector, fn) { 44 | return internals.turnOn(delegator, type, selector, fn); 45 | }, 46 | off: function(type, selector) { 47 | return internals.turnOff(delegator, type, selector); 48 | } 49 | }; 50 | }; -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | }, 6 | "rules": { 7 | "block-scoped-var": 2, 8 | "complexity": [ 9 | 2, 10 | 5 11 | ], 12 | "consistent-return": 2, 13 | "curly": 2, 14 | "default-case": 2, 15 | "dot-notation": 2, 16 | "eqeqeq": 2, 17 | "guard-for-in": 2, 18 | "no-alert": 2, 19 | "no-caller": 2, 20 | "no-comma-dangle": 2, 21 | "no-div-regex": 2, 22 | "no-dupe-keys": 2, 23 | "no-else-return": 2, 24 | "no-empty-label": 2, 25 | "no-eq-null": 2, 26 | "no-eval": 2, 27 | "no-extend-native": 2, 28 | "no-extra-bind": 2, 29 | "no-extra-boolean-cast": 2, 30 | "no-fallthrough": 2, 31 | "no-floating-decimal": 2, 32 | "no-implied-eval": 2, 33 | "no-labels": 2, 34 | "no-iterator": 2, 35 | "no-lone-blocks": 2, 36 | "no-loop-func": 2, 37 | "no-multi-str": 2, 38 | "no-native-reassign": 2, 39 | "no-new": 2, 40 | "no-new-func": 2, 41 | "no-new-wrappers": 2, 42 | "no-octal": 2, 43 | "no-octal-escape": 2, 44 | "no-proto": 2, 45 | "no-redeclare": 2, 46 | "no-return-assign": 2, 47 | "no-script-url": 2, 48 | "no-self-compare": 2, 49 | "no-sequences": 2, 50 | "no-unused-expressions": 2, 51 | "no-unused-vars": 1, 52 | "no-unreachable": 2, 53 | "no-void": 2, 54 | "no-with": 2, 55 | "radix": 2, 56 | "vars-on-top": 0, 57 | "wrap-iife": [ 58 | 2, 59 | "outside" 60 | ], 61 | "yoda": 2, 62 | "quotes": 0, 63 | "eol-last": 0, 64 | "no-extra-strict": 2, 65 | "camelcase": 0, 66 | "consistent-this": [ 67 | 2, 68 | "_this" 69 | ], 70 | "new-cap": 2, 71 | "new-parens": 2, 72 | "func-style": [ 73 | 2, 74 | "expression" 75 | ], 76 | "no-lonely-if": 2, 77 | "no-new-object": 2, 78 | "no-space-before-semi": 2, 79 | "brace-style": [ 80 | 2, 81 | "1tbs" 82 | ], 83 | "no-wrap-func": 2, 84 | "space-after-keywords": [ 85 | 2, 86 | "always" 87 | ], 88 | "use-isnan": 2, 89 | "valid-jsdoc": [ 90 | 2, 91 | { 92 | "prefer": { 93 | "return": "returns" 94 | } 95 | } 96 | ], 97 | "max-nested-callbacks": [2, 3], 98 | "semi": [2, "always" ], 99 | "no-underscore-dangle": 0 100 | } 101 | } -------------------------------------------------------------------------------- /dist/bundle.min.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.tye=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o