/**
 * lightweight application manager
 * @author Markus J Doetsch
 * https://github.com/mdular/app.js
 *
 * register page controllers like this:
 * app.registerController('myController, myModule[FunctionWrapper]);
 * <body id="myController">
 *
 * register modules like this:
 * app.registerModule('myModule', myModule[FunctionWrapper] [, boolean alwaysRun = false]);
 * <body data-modules="myModule myOtherModule"> (not required when alwaysRun = true)
 *
 * declare dependencies in body-tag.
 * id = controller (use server-side mvc controller or controller-action, depending on required granularity)
 * data-modules = module dependencies, separated by space
 *
 * modules are invoked before the controller
 *
 * TODO: implement additional window.load callback for controllers (to simplify lazy loading scripting)
 * TODO: inject module references into the controller
 */
/* global app:true, aight */

var app = (function () {
    "use strict";

    var modules = [];
    var globalModules = [];

    // 'load' or 'DOMContentLoaded'
    var listen = function (event) {

        window.addEventListener(event, function () {
            start();
        });

        // solve 'DOMContentLoaded' for IE < 8
        if (
            event === 'DOMContentLoaded'
            && typeof document.documentMode !== 'undefined'
            && document.documentMode === 8
        ) {
            // doScroll test method
            var t = window.setInterval(function() {
                if (window.document.body) {
                    // Check for doScroll success
                    try {
                        window.document.createElement('div').doScroll('left');
                        window.clearInterval(t);
                    } catch(e) {
                        return;
                    }
                    start();
                }
            }, 10);
        }
    };

    var start = function () {
        var body = document.getElementsByTagName('body')[0],
            modules = body.getAttribute('data-modules') || '',
            controller = body.getAttribute('id') || '';

        init(modules.split(' '));
        run([controller]);
    };

    var init = function (modulesToRun) {
        modulesToRun = modulesToRun.concat(globalModules);

        for (var i = 0, count = modulesToRun.length; i < count; i++) {
            invoke(modulesToRun[i]);
        }
    };

    var run = function (controllerName) {
        // fail nonexisting controllers silently
        if (modules[controllerName] === undefined) {
            return;
        }

        // skip if already initialized
        if (modules[controllerName].init) {
            return;
        }

        invoke(controllerName);
    };

    var reset = function (moduleName) {
        if (modules[moduleName] === undefined) {
            throw new Error('Trying to reset non-existing module: ' + moduleName);
        }

        modules[moduleName].init = false;

        // has reset function? call it
        if(typeof modules[moduleName].reset === 'function') {
            modules[moduleName].reset();
        }

        // set state
        modules[moduleName].init = false;
    };

    var invoke = function (identifier) {
        if (modules[identifier] === undefined) {
            return;
        }

        // get module
        var module = modules[identifier].module;

        // invoke module function wrapper if there is one
        if (typeof module === 'function') {
            module = module();
        }

        // init present?
        if (typeof module.init !== 'function') {
            throw new Error('invalid style: no init() found in: ' + identifier);
        }

        // finally, run it
        module.init.call(module);
        modules[identifier].module = module;
        modules[identifier].init = true;
    };

    // there is no internal difference between modules and controllers
    var registerController = function (controllerName, module) {
        registerModule(controllerName, module);

    };

    var registerModule = function (moduleName, module) {
        if (modules[moduleName] !== undefined) {
            throw new Error('module already registered: ' + moduleName);
        }

        // module should always be invoked
        if (arguments[2]) {
            globalModules.push(moduleName);
        }

        modules[moduleName] = {
            module  : module,
            init    : false
            //run     : false
        };
    };

    var getModule = function (moduleName) {
        return modules[moduleName];
    };

    return {
        listen              : listen,
        reset               : reset,
        registerController  : registerController,
        registerModule      : registerModule,
        getModule           : getModule
    };
}());

app.listen('DOMContentLoaded');

@@ -60,16 +60,31 @@
 Doetsch%0A
+ *%0A * Info:%0A *%0A
  * https
@@ -110,24 +110,40 @@
 r/app.js%0A *%0A
+ *%0A * Usage:%0A *%0A
  * register 
@@ -736,169 +736,8 @@
 ler%0A
- *%0A * TODO: implement additional window.load callback for controllers (to simplify lazy loading scripting)%0A * TODO: inject module references into the controller%0A
  */%0A
@@ -758,15 +758,8 @@
 true
-, aight
  */%0A

update description