1
\$\begingroup\$

I have to set up a new JavaScript library for a big project, which isn't Object Oriented yet. So I built a small file to test some needs. The result is the following:

var Module =
{
    Config: (function()
    {
        //- private members
        var _systemName =   'mySystem',
            _version    =   '1.1.4';

        //- private methods
        //...

        //- public methods
        var api =
        {
            getSystemInfo: function()
            {
                return "system: '"+_systemName+"' @ version "+_version;
            }
        };

        return api;
    })(),

    Dialog:
    {
        _: (function(){
            $(document).ready(function()
            {
                $('.showDialog').on('click',function()
                {
                    var obj = {
                        element:    this,
                        foo:        'foo',
                        bar:        'bar',
                        target:     $('#title')
                    };

                    Module.Dialog.setParam(obj);
                    Module.Dialog.show();
                })
            });
        })(),

        setParam: function(config)
        {
            console.log('config set for dialog box');
            console.log(config);
        },

        show: function()
        {
            console.log('dialogbox show | '+Module.Config.getSystemInfo());
        },

        close: function()
        {
            console.log('dialogbox close');
        }
    },

    Savescreen:
    {
        setParam: function(config,foo)
        {
            console.log('config set for savescreen');
        },

        show: function()
        {
            console.log('savescreen show | '+Module.Config.getSystemInfo());
        }
    }
}

Goals:

  • access via Module.Object.Function()
  • no instantiation via keyword new
  • private members and methods (in config section or event-listner)
  • easy structured and object orientated
  • each section must have its own scope (section = savescreen, config, dialogbox, etc)
  • each section should hold its event-listner
\$\endgroup\$
2
  • 5
    \$\begingroup\$ Consider putting the opening { in the same line as the statement, e.g. var foo = {. When using return you are actually required to do this so it's a good idea to do it in any case. \$\endgroup\$ Commented Mar 26, 2013 at 16:24
  • \$\begingroup\$ Agreed. You shouldn't use curly-brace-on-new-line style in JavaScript. In other languages people can argue over style preferences forever, but in JavaScript things may simply break if you use brace-on-new-line style. So the debate will at least be shorter :) \$\endgroup\$ Commented Mar 26, 2013 at 18:00

1 Answer 1

4
\$\begingroup\$

To start off, your module should be the bare minimum, but extendable (like jQuery). That way, you won't have problems with scalability and maintenance. Here's a simple module template, where everything gets declared in the Module namespace:

//this is a simple module declaration:
(function(Module){

  //everything here is private unless attached to the Module namespace
  var imPrivate = 'cant see me!';

  //here's an example of an exposed functionality
  Module.imaPublicProperty = 'public property here';

  Module.imaPublicFunction = function(){
    console.log('im public');
  }

  //here's an example privileged methods, public methods that have access
  //to the private scope. These are your "setters and getters" in Java-speak
  Module.imaPrivilegedFunction = function(){
    console.log(imPrivate);
  }

}(this.Module = this.Module || {}));

I suggest you build a helper function that actually appends your sections to your namespace. That way, the module would scale easily. Also, you don't have to fiddle with the base-code and lose commas along the way.

Here's a simple, yet incomplete implementation using this new approach (it lacks the document.ready part). It is long, yet it's modular and easily maintainable. You can even split the section codes in separate files.

(function (ns) {

  ns.addSection = function (name, def) {
    ns[name] = new def();
  }

}(this.Module = this.Module || {}));

//adding config
Module.addSection('Config', function () {
  var systemName = 'mySystem',
    version = '1.1.4',
    section = this;

  section.getSystemInfo = function () {
    return systemName + ' v' + version;
  }

});

//adding Dialog
Module.addSection('Dialog', function () {

  var section = this;

  section.onDocumentReady = function () {
    $('.showDialog').on('click', function () {
      var obj = {
        element: this,
        foo: 'foo',
        bar: 'bar',
        target: $('#title')
      };
      section.setParam(obj);
      section.show();
    })
  }

  section.setParam = function (config) {
    console.log('config set for dialog box');
    console.log(config);
  }

  section.show = function () {
    console.log('dialogbox show | ' + Module.Config.getSystemInfo());
  }

  section.close: function () {
    console.log('dialogbox close');
  }

});

//Savescreen section
Module.addSection('Savescreen', function () {

  var section = this;

  section.setParam = function (config, foo) {
    console.log('config set for savescreen');
  }

  section.show = function () {
    console.log('savescreen show | ' + Module.Config.getSystemInfo());
  }

});

Here's how it's possibly used:

Module.Config.getSystemInfo();
//mySystem v1.1.4

So basically, you have base code and you just append to the namespace the sections via a helper function. Keeps the code clean and loose.

I suggest looking at KernelJS, which implements this pattern

\$\endgroup\$
1
  • \$\begingroup\$ thank you very much Joseph! looks very very smooth and has a excellent structure! thanks a lot! \$\endgroup\$ Commented Mar 28, 2013 at 16:41

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.