Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern for Javascript Module Pattern and Sub-Module Initialization

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.

like image 418
mpdonadio Avatar asked Feb 22 '11 20:02

mpdonadio


People also ask

What is JavaScript module pattern?

In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope.

What is module pattern in node JS?

What is Module Pattern? The module pattern is a special Design pattern in which we use IFFI (Immediately invoked function expression), and we return an object. Inside of that object, we can have functions as well as variables.

What is modular design pattern?

In software engineering, the module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept.

Which access levels are available in module design pattern?

The module pattern allows for public and private (plus the lesser-know protected and privileged) access levels. Notice that callChangeHTML binds to the returned object and can be referenced within the HTMLChanger namespace. However, when outside the module, contents are unable to be referenced.


1 Answers

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>
like image 92
Raynos Avatar answered Nov 15 '22 17:11

Raynos