{"size": 2676, "ext": "js", "max_stars_repo_path": "src/utils/delegate.js", "max_stars_repo_name": "toothrot-if/toothrot-ide", "max_stars_repo_stars_event_min_datetime": "2017-12-26T17:42:38.000Z", "max_stars_repo_stars_event_max_datetime": "2019-09-10T10:47:57.000Z", "max_issues_repo_path": "src/utils/delegate.js", "max_issues_repo_name": "toothrot-if/toothrot-ide", "max_issues_repo_issues_event_min_datetime": "2020-09-26T04:41:17.000Z", "max_issues_repo_issues_event_max_datetime": "2020-09-26T04:41:17.000Z", "max_forks_repo_path": "src/utils/delegate.js", "max_forks_repo_name": "toothrot-if/toothrot-ide", "max_forks_repo_forks_event_min_datetime": "2019-10-05T13:31:32.000Z", "max_forks_repo_forks_event_max_datetime": "2019-10-05T13:31:32.000Z"}
{"max_stars_count": 2, "max_issues_count": 1, "max_forks_count": 1, "avg_line_length": 23.4736842105, "max_line_length": 86, "alphanum_fraction": 0.5209267564}

var TARGET_ATTRIBUTE = "data-type";

function contains (collection, item) {
    return collection.indexOf(item) >= 0;
}

function findNearestTarget (event) {
    
    var target = event.target;
    
    while (target && target !== document.documentElement) {
        
        if (target.hasAttribute(TARGET_ATTRIBUTE)) {
            return target;
        }
        
        target = target.parentElement;
    }
    
    return target;
}

function delegate (element) {
    
    var listeners = {};
    var handlers = {};
    
    function on (eventName, type, handler) {
        
        if (hasHandler(eventName, type, handler)) {
            return;
        }
        
        ensureHasEventType(eventName, type);
        handlers[eventName][type].push(handler);
    }
    
    function destroy () {
        
        unsubscribeAll();
        
        handlers = null;
    }
    
    function unsubscribeAll () {
        Object.keys(listeners).forEach(function (key) {
            element.removeEventListener(key, listeners[key]);
        });
    }
    
    function hasHandler (eventName, type, handler) {
        return (
            handlers[eventName] &&
            handlers[eventName][type] &&
            contains(handlers[eventName][type], handler)
        );
    }
    
    function ensureHasEventType (eventName, type) {
        
        ensureHasEvent(eventName);
        
        if (!handlers[eventName][type] || !Array.isArray(handlers[eventName][type])) {
            handlers[eventName][type] = [];
        }
    }
    
    function ensureHasEvent (eventName) {
        
        if (!listeners[eventName]) {
            listeners[eventName] = listen(eventName);
        }
        
        if (!handlers[eventName] || typeof handlers[eventName] !== "object") {
            handlers[eventName] = {};
        }
    }
    
    function listen (eventName) {
        
        function listener (event) {
            
            var target = findNearestTarget(event);
            var type = target ? target.getAttribute(TARGET_ATTRIBUTE) : null;
            
            event.stopPropagation();
            
            if (type) {
                fire(eventName, type, event);
            }
        }
        
        element.addEventListener(eventName, listener);
        
        return listener;
    }
    
    function fire (eventName, type, event) {
        if (handlers[eventName] && Array.isArray(handlers[eventName][type])) {
            handlers[eventName][type].forEach(function (handler) {
                handler(event);
            });
        }
    }
    
    return {
        on: on,
        destroy: destroy
    };
}

module.exports = delegate;
