UNPKG

bbop-registry

Version:

Generic lightweight listener/callback registry system.

178 lines (151 loc) 5.2 kB
/* * Generic lightweight listener/callback registry system. * * @module: bbop-registry */ var us = require('underscore'); var each = us.each; var bbop = require('bbop-core'); /** * Contructor for BBOP registry. Takes a list of event categories as * strings. * * @constructor * @param {Array} evt_list - a list of strings that identify the events to be used * @returns {Object} bbop registry object */ var registry = function(evt_list){ this._is_a = 'bbop-registry'; var registry_anchor = this; // Handle the registration of call functions to get activated // after certain events. this.callback_registry = {}; each(evt_list, function(item, i){ registry_anchor.callback_registry[item] = {}; }); /** * Add the specified function from the registry, with an optional * relative priority against other callback functions. * * The in_priority value is relative to others in the category, * with a higher priority...getting priority. * * See also: <apply> * * @param {String} category - one of the pre-defined categories * @param {Function} in_function - function * @param {Number} [in_priority] - the higher the faster * @param {String} [function_id] - a unique string to identify a function; generated if one is not given * @returns {String} the ID for the registered function in the given category */ this.register = function(category, in_function, in_priority, function_id){ // Only these categories. if( typeof(registry_anchor.callback_registry[category]) === 'undefined'){ throw new Error('cannot register unknown category'); } // The default priority is 0. var priority = 0; if( in_priority ){ priority = in_priority; } // The default ID is generated, but take one if given. var fid = null; if( function_id ){ fid = function_id; }else{ fid = bbop.uuid(); } // Final registration. registry_anchor.callback_registry[category][fid] = { runner: in_function, priority: priority }; return fid; }; /** * Returns whether or not an id has already been registered to a * category. Will return null if the category does not exist. * * @param {String} category - one of the pre-defined categories * @param {String} function_id - a unique string to identify a function * @returns {Boolean|null} true, false, or null */ this.is_registered = function(category, function_id){ var retval = null; var anc = registry_anchor.callback_registry; // if( typeof(anc[category]) !== 'undefined'){ retval = false; if( typeof(anc[category][function_id]) !== 'undefined'){ retval = true; } } return retval; }; /** * Remove the specified function from the registry. Must specify a * legitimate category and the function id of the function in it. * * @param {String} category - string * @param {String} function_id - string * @returns {Boolean} boolean on whether something was unregistered */ this.unregister = function(category, function_id){ var retval = false; if( registry_anchor.callback_registry[category] && registry_anchor.callback_registry[category][function_id] ){ delete registry_anchor.callback_registry[category][function_id]; retval = true; } return retval; }; /** * Generic getter for callback functions, returns by priority. * * @param {String} category - string * @returns {Array} an ordered (by priority) list of function_id strings */ this.get_callbacks = function(category){ var cb_id_list = us.keys(registry_anchor.callback_registry[category]); // Sort callback list according to priority. var ptype_registry_anchor = this; cb_id_list.sort( function(a, b){ var pkg_a = ptype_registry_anchor.callback_registry[category][a]; var pkg_b = ptype_registry_anchor.callback_registry[category][b]; return pkg_b['priority'] - pkg_a['priority']; }); // Collect the actual stored functions by priority. var cb_fun_list = []; for( var cbi = 0; cbi < cb_id_list.length; cbi++ ){ var cb_id = cb_id_list[cbi]; var to_run = registry_anchor.callback_registry[category][cb_id]['runner']; cb_fun_list.push(to_run); // ll('callback: ' + category + ', ' + cb_id + ', ' + // this.callback_registry[category][cb_id]['priority']); } return cb_fun_list; }; /** * Generic runner for prioritized callbacks with various arguments * and an optional change in context.. * * @param {String} category - string * @param {Array} arg_list - a list of arguments to pass to the function in the category * @param {String} [context] - the context to apply the arguments in */ this.apply_callbacks = function(category, arg_list, context){ // Run all against registered functions. var callbacks = registry_anchor.get_callbacks(category); for( var ci = 0; ci < callbacks.length; ci++ ){ var run_fun = callbacks[ci]; //run_fun(arg_list); run_fun.apply(context, arg_list); } }; }; /// /// Exportable body. /// module.exports = registry;