Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // -----------------------------------------------------------------------------
- // generic namespace generator the constructor should declare private functions
- // and variables and return public api, the module is created when all dependecies
- // are resolved (all modules are created)
- //
- // @param namespace dot separated namespace that will be added to window object
- // @param dependencies array of string (dependencies) can be empty array
- // @param constructor function that should return public module API
- //
- // usage:
- // module('app.projects', ['app.helpers'], function(helpers) {
- // console.log(app.helpers === helpers);
- // helpers.log('hello');
- // return {
- // foo: function() {
- // helpers.log('foo');
- // }
- // };
- // });
- // module('app.helpers', [], function() {
- // return {
- // log: function(msg) {
- // console.log(msg);
- // }
- // };
- // });
- // -----------------------------------------------------------------------------
- var module = (function() {
- // to keep track of dependecies, real objects are nested in window
- var modules = {};
- // ---------------------------------------------------------------------------
- function init(module) {
- var dependecies = module.dependencies.map(function(name) {
- if (!modules[name]) {
- throw new Error('module ' + name + ' not defined when init ' + module.name);
- }
- return modules[name].module;
- });
- Object.assign(module.module, module.constructor.apply(null, dependecies));
- }
- // ---------------------------------------------------------------------------
- function concat(array) {
- array = array.slice()
- if (array.length > 1) {
- var last = array.pop();
- return array.join(', ') + ' and ' + last;
- } else {
- return array[0];
- }
- }
- // ---------------------------------------------------------------------------
- return function module(namespace, dependencies, constructor) {
- var names = namespace.split('.');
- var current = window;
- names.forEach(function(name) {
- if (!current[name]) {
- current[name] = {};
- }
- current = current[name];
- });
- if (modules[namespace]) {
- throw new Error('Module ' + namespace + ' already defined');
- }
- var module = modules[namespace] = {
- name: namespace,
- module: current,
- dependencies: dependencies,
- constructor: constructor
- };
- // if dependencies not resolved
- if (dependencies.length) {
- // are all dependentant modules loaded?
- var foundDepenencies = dependencies.filter(function(dependency) {
- return modules[dependency];
- });
- if (foundDepenencies.length === dependencies.length) {
- init(module);
- }
- } else {
- // no depeendecies
- init(module);
- }
- var modulesWithDependecies = Object.keys(modules).filter(function(name) {
- var module = modules[name];
- // don't process self and modules that don't have dependencies,
- // those was already loaded
- return Object.keys(module.dependencies).length;
- });
- modulesWithDependecies.filter(function(name) {
- return name !== namespace;
- }).forEach(function(name) {
- var module = modules[name];
- var dependats = module.dependencies;
- var resolved = dependats.filter(function(key) {
- return modules[key];
- });
- // init modules that have resolved dependecies
- if (resolved.length == dependats.length) {
- init(module);
- } else {
- // find mutual dependecies
- if (dependats.length) {
- var mutualDependant = modulesWithDependecies.filter(function(searchName) {
- var searchModule = modules[searchName];
- return Object.keys(searchModule.dependencies).indexOf(name) !== -1;
- });
- if (mutualDependant.length) {
- var brokenModules = mutualDependant.concat([name]);
- // this will show error in toaster and log in server because of window
- // error handler in error.js
- throw new Error(concat(brokenModules) + ' have mutual dependecy');
- }
- }
- }
- });
- };
- })();
Add Comment
Please, Sign In to add comment