(function(){ var Application = (function(){ // With this framework, multiple applications can be created on the same page. Because of this, // each application has its own "Core". The Core contains all the functionality, registered events, // etc. for the application. var ApplicationCores = {}; // Check if the console exist and create a dummy console if not if (!window.console || !console.firebug){ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) { window.console[names[i]] = function(){} } } // This function creates a new application core function createApplication(){ // All modules get saved into this object. Every object must be uniquely named var modules = {}; // All registered events are stored in this object with associated handlers var eventRegistry = {}; // The function to execute to create a new sandbox instance for each module var sandboxConstructor; // Each extension the user adds to the sanbox get stored here. Once a new instance is // created, the array is looped through and the extensions are copied to the sandbox. // When I say "extension" I basically mean just function. var sandboxExtensions = []; // Stores the Logger object and ErrorHandler if one is present var utils = {}; // The default configuration values var config = { enableLogging: false, handleErrors: false }; // Simply loads any new configuration values into the application function loadConfig(configuration){ if(configuration.enableLogging){ config.enableLogging = true; } if(configuration.handleErrors){ config.handleErrors = true; } } function start(moduleName,args){ var instance = modules[moduleName].module(getSandbox()); var name; var method; var eventRegistry = {}; if (config.enableLogging || config.handleErrors){ for (name in instance) { method = instance[name]; if (typeof method == "function"){ instance[name] = (function(name, method){ return function(){ try { if(config.enableLogging){ if (getLogger()) { getLogger().log("Method Executed: " + moduleName + "." + name + "()", {args: arguments}); } else { console.log("Method Executed: " + moduleName + "." + name + "()", {args: arguments}); } } return method.apply(this, arguments); } catch (e) { if (config.handleErrors && getErrorHandler()) { getErrorHandler().handleError(e); } else { throw e; } } }; })(name, method); } } } modules[moduleName].instance = instance; if (instance.init) { instance.init(args); } } function stop(moduleName){ if (modules[moduleName].instance !== null){ if (modules[moduleName].instance["destroy"]) { modules[moduleName].instance.destroy(); } modules[moduleName].instance = null; } } function startAll(){ var name; for (name in modules){ start(name); } } function stopAll(){ var name; for (name in modules){ stop(name); } } function listen(events,method,object){ var i = 0; for(i=0; i<=events.length-1; i++){ if (!eventRegistry[events[i]]) { eventRegistry[events[i]] = []; } eventRegistry[events[i]].push({subscriber: object, handler: method}); } } function broadcast(event,data){ var i = 0; var subscriber; var handler; var key; if (getLogger()) { getLogger().log("Event Broadcast: " + event,data); } if(!eventRegistry[event]){ return; } for(key in eventRegistry[event]){ subscriber = eventRegistry[event][key].subscriber; handler = eventRegistry[event][key].handler; handler.apply(subscriber,arguments); } } function registerModule(name,module){ var definition = {}; definition.name = name; definition.module = module; definition.instance = null; if (!modules[name]) { modules[name] = definition; } else { throw new Error("The module " + name + " already exists.") } } function registerSandbox(constructor){ sandboxConstructor = constructor; }; function addSandboxExtension(name,fn){ if(!name || !fn){ throw new Error("An extension must have both a name and function defined."); } sandboxExtensions.push({name: name, fn: fn}); }; function getSandbox(){ var i = 0; var sandbox = sandboxConstructor(self); for(i=0; i<=sandboxExtensions.length-1; i++){ sandbox[sandboxExtensions[i].name] = sandboxExtensions[i].fn; } return sandbox; } function registerLogger(logger){ if(!logger.log){ throw new Error("The Logger must have a 'log' method defined."); } if(!logger.error){ throw new Error("The Logger must have a 'error' method defined."); } utils.logger = logger; } function getLogger(){ return utils.logger; } function registerErrorHandler(errorHandler){ if(!errorHandler.handleError){ throw new Error("The ErrorHandler must have a 'handleError' method defined."); } utils.errorHandler = errorHandler; } function getErrorHandler(){ return utils.errorHandler; } // Register a default sandbox registerSandbox(function(application){ return { listen: function(events,method,object){ application.events.listen(events,method,object); }, broadcast: function(event,data){ application.events.broadcast(event,data); } } }); var self; return self = { loadConfig: loadConfig, events: { listen: listen, broadcast: broadcast }, modules: { register: registerModule, start: start, stop: stop, startAll: startAll, stopAll: stopAll }, sandbox: { register: registerSandbox, addExtension: addSandboxExtension }, util: { registerLogger: registerLogger, registerErrorHandler: registerErrorHandler } } } return { init: function(name,fn){ if(ApplicationCores[name]){ throw new Error("Application " + name + " already exists."); } else{ ApplicationCores[name] = createApplication(); fn(ApplicationCores[name]); } }, get: function(name){ return ApplicationCores[name]; } }; })(); window.Application = Application; })();