Source: public/src/util/hooks.js

/**
 * Hook system to modify simple things.
 * 
 * @module util/hooks
 * @see Events for hook events
 * @example <caption>Accessing the hook system</caption>
 * window.rml.hooks.register("yourAction", function() {
 *  // Do something
 * });
 */
import $ from 'jquery';

const registry = {}, hooks = {
    /**
     * Registers a callback to a given event name.
     * 
     * @param {string} names The event name, you can also pass multiple names when splitted with " "
     * @param {function} callback The callback function with the arguments
     * @returns {module:util/hooks}
     * @function register
     */
    register(names, callback) {
        names.split(' ').forEach(name => {
           registry[name] = registry[name] || [];
           registry[name].push(callback);
        });
        return hooks;
    },
    
    /**
     * Deregister a callback to a given event name.
     * 
     * @param {string} name The event name
     * @param {function} callback The callback function with the arguments
     * @returns {module:util/hooks}
     * @function register
     */
    deregister(name, callback) {
        let i;
        if (registry[name]) {
            registry[name].forEach(fns => {
                i = fns.indexOf(callback);
                i > -1 && fns.splice(i, 1);
            });
        }
        return hooks;
    },
    
    /**
     * Call an event.
     * 
     * @param {string} name The event name
     * @param {mixed[]} args Pass arguments to the callbacks
     * @param {object} context Pass context to the callbacks
     * @returns {module:util/hooks}
     * @function call
     */
    call(name, args, context) {
        if (registry[name]) {
            if (args) {
                if (Object.prototype.toString.call(args) === '[object Array]') {
                    args.push($);
                }else{
                    args = [args, $];
                }
            }else{
                args = [$];
            }
            
            // When explicit false then break the for
            registry[name].forEach((callback) => callback.apply(context, args) !== false);
        }
        return hooks;
    },
    
    /**
     * Checks if a event name is registered.
     * 
     * @param {string} name The event name
     * @returns {boolean}
     * @function exists
     */
    exists(name) {
        return !!registry[name];
    }
};

export default hooks;