13

I am starting up a new project and I am reviewing my best-practices to try to prevent any problems, and also to see what bad habits I have gotten into.

I am not terribly pleased with how I am handling initialization sequences in Javascript using the module / submodule pattern.

Let's say, my code ends up with something like

FOO.init()
FOO.module1.init()
FOO.module2.init()
FOO.module3.init()
FOO.module4.init()

at the global scope.

I am essentially doing (error checking and details omittied for brevity):

var FOO = (function (me) {
    me.init = function () {
        for (var i in me.inits) {
            me.inits[i]();
        }
    }

    return me; 
}(FOO || {}));

var FOO = (function (parent) {
    var me = parent.module1 = parent.module1 || {};

    me.init = function () {
    }

    parent.inits.push(me.init);

    return parent;
}(FOO || {}));

$(document).ready(FOO.init);

for initialization.

I know I have read up on this before, but I can't come up with the right search terms to find the articles now. Is there a well thought out and tested pattern that handles initialization in sitiation like this?

Thanks.

EDIT: Upon re-reading this, I think a little context will inform answers.

In my case, each module / submodule is in its own file. The base module defines the basic functionality of the site, and sub-modules enable different features. For example, a sub-module may wire up auto-completion on a search box, and another may turn a static header image into a rotating banner. Sub-modules are enabled/disabled by the CMS, so I really do want to divorce explicit calls inside the base module so everything can be managed by the CMS. I also that there are CMS specific ways to accomplish this, but I looking for a generic Javascript pattern for doing this to provide consistency and resuablity between projects that may use a different CMS.

1 Answer 1

18

I personally have a different coding style to that. This is one of them. The other is basically an imitation of the style used in backbone.js

var myProgram = (function() {
   var someGlobal, someGlobal2;   

   var subModule1 = (function() {
       ...       

       var init = function() {

       };

       ...

       init();

       return { 
           "someMethod": someMethod,
           ...
       };
   }());

   var OtherSubModule = (function() {
       ...
       var init = function(param) { ... };
       ...
       return { 
           "init": init,
           ...
       };
   }());

   var init = function(param) {
       ...

       OtherSubModule.init({
           "foo": param.foo,
           "bar": param.bar,
           ...
       });
   };


   return { 
       "init": init,
       "somePublic": OtherSubModule.foobar, 
       ...
   }
}());

Depends whether I need to supply a public API to other users, which backbone does a lot better. I prefer to make modules driven by an init function for initial configuration and for the rest completely event driven.

[Edit]

Given the edited question I have a different pattern for this. Each file defines a function on some object in my case it was $.FooBar.plugins

(function() {

    var foo = function() { ... };

    var bar = (function() { ... }());

    myNamespace.plugins["MyPlugin"] = function() {

        ... do stuff
        ... bind to evevnts
    };

}());

Then we use a boot strapper that was something like this :

(function() {

    var needed = function() {
         // Feature detection
    };

    var load = function() { ... };

    var getOptions = function() {
         // Call something on a page by page basis.
    };

    for (var plugin in pluginList) {
         if (needed(plugin)) {
               load(plugin, function() {
                    // get page specific options
                    var options = getOptions();
                    // run plugin
                    myNameSpace.plugins[plugin](options);
                    // If all have been loaded trigger ready handlers
                    if (pluginCurrentCount == pluginCount) {
                         readyTrigger();
                    }
               });
               pluginCount++;
         }
    }

    // start loading plugins after all have been counted
    load.startLoading();

    var readyTrigger = function() {
         // Run all ready handlers
    }

    // Implement your own DOM ready function to run when all plugins
    // have loaded.
    myNameSpace.ready = function(handler) {
         if (isReady) {
             handler();
         } else {
             readyList.push(handler);
         }

    };
}());

That's a lot of gaps and pseudo code but you should get the idea. If it's not obvouis feel to question it.

Then on the page we have something like this

<html>
<head>
  <script type="text/javascript">

    var pageSpecific = {
         "pluginName": {
              "cssClass": "foobar",
              "submitOnEnter": false,
              ...
         },
         ...
    };

  </script>
  <script src="bootstrapper.js" />
  ...
</head>
<body>
  ...
</body>
</html>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. My real code is somewhat closer to your second example, which makes me feel better about my approach. Your example did also give me a few ideas for improvement, too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.