Click here to Skip to main content
14,028,475 members
Click here to Skip to main content
Add your own
alternative version

Stats

20.1K views
9 bookmarked
Posted 9 Feb 2016
Licenced MIT

The JavaScript Module Pattern With jQuery

, 10 Feb 2016
Rate this:
Please Sign up or sign in to vote.
The JavaScript Module Pattern used with jQuery

Introduction

I have always been primarily a backend developer, I love OOP, and try my best to follow all the best principles such as Encapsulation, Polymorphism, Separation of Concerns, and even the Law of Demeter when I design and write software. As such, I have fought tooth and nail to avoid writing in-browser apps. I have nothing against them, I believe that’s where the View needs to be... philosophically. I just want someone else to do it, to deal with the JavaScript and CSS because it’s so hard to disciple ourselves to writing good, clean code. OOP code in the browser with JavaScript ES5 isn't difficult to write correctly, it’s just easy not to. (In future articles, I’ll discuss how I’ve overcome this with Angular 2, Typescript, and even ES6 features)

Background

Here we introduce the Module Pattern, this gives us a way in JavaScript to introduce private variables and functions, exposing only those parts we need to the outside world. There are several flavors of this available, you can implement it as a JavaScript object, you can use prototypes, or you can write it as an IIFE a JavaScript Immediately Invoked Function Expression. To do this, we implement a JavaScript Closure. More about closures here.

Using the Code

Enjoy the sample, and remember, it’s just a sample as each case may call for something a little different. For example, I’ve separated Init() and showMessage() functionality which in many cases can be combined.
Note: This code is not designed to be functional but to be used as a template.

/// JavaScript source code representing example jQuery aware module pattern
/// Solution Zero, Inc. Lubbock Texas 
/// Troy Locke -- troy@slnzero.com
var myMessageApp = (function() {
    "use strict"

    // I avoid these with the bindControls functionality but I show if for example.
    var someElement = $("#foo"); // some element I know I'll use lots

    // private variables
    var pvtMessageVal;
    var pvtAdditionalMessageVal;
    
    // we create an object to hold all the jQuery controls, so we can call
    // binding after loading an HTML page dynamically via AJAX
    // see bindControls further down
    var messageCtrls = {};

    var config = {
        // *example, this must be passed into init(config)
        fooSelector: null, // $("#foo")
        messageSelector: null, // $(".message")
        additionalMessageSelector: null, // $(".additional_message")
        options: {
            showOK: true,
            showCancel: true,
            warningLevel: 1,
        }
    }

    // AJAX calls
    var getMessage = function(message) {
        $.ajax({
            url: '/getMessagePage',
            type: 'POST',
            dataType: "json",
            data: {'message' : message},
            success: function(data) {
                // ...
                messageCtrls.mainMessageDiv.html(data.message);
                // call bind controls to bind to the newly introduced dom elements
                messageCtrls = bindMessageControls();
                },
            error: function() {
                // ...
                }
        });
    };

    var inputClick = function(event) {
        event.preventDefault();
        // depending on if you'll reuse these selectors throughout 
        // the app I might have these as variables
        $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

        // try to avoid these
        var msg = $(".additionalMessage").val();
        // and use this 
        var msg = config.additonalMessageSelector.val();
        // or
        var msg = pvtAdditionalMessageVal;

        if (msg == ""){
            $("#message_empty").jmNotify();
            $('.remove_loading').remove();
        } else {
            getMessage(msg);
        }
    };

    var bindMessageControls = function () {
        var self = {};

        // Modal
        self.thisModal = $(".MessageModal");

        // CheckBoxs
        self.fooCb = $(".foo_checkbox");
        
        // Buttons
        self.okBtn = $(".btnOk");
        self.cancelBtn = $(".btnCancel");

        // Divs
        self.mainMessageDiv = $(".main_message");
        self.additionalMessageDiv = $(".addtional_message");

        //Help Icons
        self.HelpIcon = $(".help-icon");

        return self;
    };

    var bindVals = function () {
        //check to make sure we have a valid config passed in before we set the values
        if (!config.messageSelector) throw "Invalid configuration object passed in init()";
        
        //bind the values to "private variables"
        pvtMessageVal = config.messageSelector.val();
        
        //this control is optional, test existence
        if(config.additionalMessageSelector.length)
            pvtAdditionalMessageVal = config.additionalMessageSelector.val();
    };

    var bindFunctions = function() {
        // you can use jQuery
        $("btnOk").on("click", inputClick)
        // but we have the controls object to use, so instead
        messageCtrls.okBtn.on('click, inputClick')
    };

    var init = function () {
        messageCtrls = bindMessageControls();
        bindFunctions();
    };

    var showMessage = function (cfg) {
        config = cfg;
        bindVals();
        messageCtrls.thisModal.modal({
            show: true,
            keyboard: false,
            backdrop: "static"
        });
    };
    
    return {
        init: init,
        show: showMessage,
        getMessage: getMessage
        //anything else you want available
        //through myMessageApp.function()
        //or expose variables here too
    };

})();
 
//usage
$("document").ready(function () {
    myMessageApp.init();
});

Points of Interest

This is the first in a series that will explore the Module Pattern in JavaScript. In the next part, I will break down the code in this example and explain in detail the whats and whys. Then I hope to show examples of other implementation of this pattern using objects, prototypes, and other variations such as the Revealing Module Pattern.

History

I'm a backend developer by trade moving into the in browser arena, so my post tends to be an effort to find a way to force structure on web development. If anyone else struggles in this area, please feel free to contact me.

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

Troy W. Locke
Software Developer (Senior) Solution Zero, Inc.
United States United States
I'm an avid consumer of technology and always trying to learn the next new latest greatest thing. I've been a back-end developer for 20 years on platforms ranging from Microsoft's stack to Django ... Windows to Linux. I've been moving my skill set towards tackling in browser apps over the last year, and enjoying the challenge (I've been engrossed in Angular 2 of late). I'm pay my rent working at Solution Zero, a coding shop where we all write software all day.

Main blog site is here.

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
Tridip Bhattacharjee10-Feb-16 20:50
professionalTridip Bhattacharjee10-Feb-16 20:50 
GeneralRe: My vote of 5 Pin
Troy W. Locke11-Feb-16 5:11
professionalTroy W. Locke11-Feb-16 5:11 
GeneralMy vote of 5 Pin
Camilo Reyes9-Feb-16 16:02
professionalCamilo Reyes9-Feb-16 16:02 
GeneralRe: My vote of 5 Pin
Troy W. Locke10-Feb-16 3:49
professionalTroy W. Locke10-Feb-16 3:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.190419.4 | Last Updated 10 Feb 2016
Article Copyright 2016 by Troy W. Locke
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid