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.
var myMessageApp = (function() {
"use strict"
var someElement = $("#foo");
var pvtMessageVal;
var pvtAdditionalMessageVal;
var messageCtrls = {};
var config = {
fooSelector: null,
messageSelector: null,
additionalMessageSelector: null,
options: {
showOK: true,
showCancel: true,
warningLevel: 1,
}
}
var getMessage = function(message) {
$.ajax({
url: '/getMessagePage',
type: 'POST',
dataType: "json",
data: {'message' : message},
success: function(data) {
messageCtrls.mainMessageDiv.html(data.message);
messageCtrls = bindMessageControls();
},
error: function() {
}
});
};
var inputClick = function(event) {
event.preventDefault();
$('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');
var msg = $(".additionalMessage").val();
var msg = config.additonalMessageSelector.val();
var msg = pvtAdditionalMessageVal;
if (msg == ""){
$("#message_empty").jmNotify();
$('.remove_loading').remove();
} else {
getMessage(msg);
}
};
var bindMessageControls = function () {
var self = {};
self.thisModal = $(".MessageModal");
self.fooCb = $(".foo_checkbox");
self.okBtn = $(".btnOk");
self.cancelBtn = $(".btnCancel");
self.mainMessageDiv = $(".main_message");
self.additionalMessageDiv = $(".addtional_message");
self.HelpIcon = $(".help-icon");
return self;
};
var bindVals = function () {
if (!config.messageSelector) throw "Invalid configuration object passed in init()";
pvtMessageVal = config.messageSelector.val();
if(config.additionalMessageSelector.length)
pvtAdditionalMessageVal = config.additionalMessageSelector.val();
};
var bindFunctions = function() {
$("btnOk").on("click", inputClick)
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
};
})();
$("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.