/** * Sets up the humhub namespace and module management. * This namespace provides the following functions: * * initModule - for adding modules to this namespace and initializing them * * @type @exp;humhub|@call;humhub.core_L4|Function */ var humhub = humhub || (function($) { /** * Contains all modules by namespace e.g. modules.ui.modal * @type object */ var modules = {}; /** * Used to collect modules added while initial page load. * These modules will be intitialized after the document is ready. * @type Array */ var initialModules = []; /** * Is set wehen document is ready * @type Boolean */ var initialized = false; /** * Adds an module to the namespace. And initializes either after dom is ready. * The id can be provided either as * * - full namespace humhub.modules.ui.modal * - or module.ui.modal * - or short ui.modal * * Usage: * * humhub.initModule('ui.modal', function(module, require, $) {...}); * * This would create an empty ui namespace (if not already created before) and * initializes the given module. * * The module can export functions ans properties by * using either * * module.myFunction = function() {...} * ... * * or * * module.export({ * myFunction: function() {...}, * ... * }); * * The export function can be called as often as needed (but should be called * once at the end of the module). * A module can provide an init function, which is called automatically * after the document is ready. * * Dependencies: * * The core modules are initialized in a specific order to provide the needed * dependencies for each module. The order is given by the order of initModule calls * and in case of core modules configured in the build script. * * A module can be received by using the required function within a module bock. * You can either depend on a module at initialisation time or within your functions. * * Usage: * * var modal = require('ui.modal); * * @param {type} id the namespaced id * @param {type} module * @returns {undefined} */ var initModule = function(id, module) { //Create module in the namespace and add helper functions var instance = resolveNameSpace(id, true); instance.id = 'humhub.modules.'+_cutModulePrefix(id); instance.require = require; instance.export = function(exports) { $.extend(instance, exports); }; //Setup the module module(instance, require, $); //Initialize the module when document is ready if(!initialized) { initialModules.push(instance); } else { instance.init(); } }; /** * Returns a module by its namespace e.g: * * For the module humhub.modules.ui.modal you can search: * * require('ui.modal'); * require('modules.ui.modal'); * require('humhub.modules.ui.modal'); * * @param {type} moduleId * @returns object - the module instance if already initialized else undefined * * */ var require = function(moduleNS) { var module = resolveNameSpace(moduleNS); if(!module) { //TODO: load remote module dependencies console.warn('No module found for id: '+moduleNS); } return module; }; /** * Search the given module namespace, and creates the given namespace * if init = true. * @param {type} typePath the searched module namespace * @param {Boolean} init - if set to true, creates namespaces if not already present * @returns object - the given module */ var resolveNameSpace = function(typePath, init) { try { //cut humhub.modules prefix if present var moduleSuffix = _cutModulePrefix(typePath); //Iterate through the namespace and return the last entry var result = modules; $.each(moduleSuffix.split('.'), function(i, subPath) { if(subPath in result) { result = result[subPath]; } else if(init) { result = result[subPath] = {}; } else { result = undefined; //path not found return false; //leave each loop } }); return result; } catch(e) { //TODO: handle could not resolve type/namespace error return; } }; /** * Cuts the prefix humub.modules or modules. from the given value. * @param {type} value * @returns {unresolved} */ var _cutModulePrefix = function(value) { return _cutPrefix(_cutPrefix(value, 'humhub.'), 'modules.'); }; /** * Cuts a prefix from a string, this is already available in humhub.util but * this is not accessible here. * * @param {type} value * @param {type} prefix * @returns {unresolved} */ var _cutPrefix = function(value, prefix) { if(!_startsWith(value, prefix)) { return value; } return value.substring(prefix.length, value.length); }; /** * Checks if a string strats with a given prefix * @param {type} val * @param {type} prefix * @returns {Boolean} */ var _startsWith = function(val, prefix) { if(!val || !prefix) { return false; } return val.indexOf(prefix) === 0; }; //Initialize all initial modules $(document).ready(function() { $.each(initialModules, function(i, module) { if(module.init) { module.init(); } initialized = true; console.log('Module initialized: '+module.id); }); }); return { initModule: initModule }; })($);