I'm writing to you all because I would like to have some advice and tips about a characteristic module pattern that I'm using.
Searching the topic on the web and in books, I couldn't find anything similar to this architectural choice, except for certains concepts.
The pattern in few words: ° Every webpage must include only one scope, and could include many modules. ° Every module is an IIFE, with subfunctions. ° Every scope has a document ready and calls one or many modules.
I attach you a code example to be more explicative.
Does this pattern reminds you something already seen before? Is a good architectural choice? Any weak points or architectural mistakes in this pattern? Is this a good use of IIFE functions and namespaces?
Thank you in advance, best regards.
index.html
<html>
<head>
<meta HTTP-EQUIV='content-type' CONTENT='text/html; charset=utf-8'/>
</head>
<body>
<div id="first"></div>
<div id="second" style="border:2px solid green;width:150px;height:190px;"></div>
</body>
<script type='text/javascript' src='http://code.jquery.com/jquery-latest.min.js'></script>
<script type='text/javascript' src='js/module.one.js'></script>
<script type='text/javascript' src='js/module.two.js'></script>
<script type='text/javascript' src='js/scope.js'></script>
module.one.js
(function () {
// Module namespace
if (typeof $M === 'undefined') {
$M = {};
}
// Variables declaration chained
var
$first,
$second,
$chunk,
documentHeight,
animationTime,
style,
style2;
/* ===========================================================================================================
INIT FUNCTION
============================================================================================================= */
var init = function() {
// calls setup first
setup();
// calls other functions
appendChunk();
animateChunk();
};
function setup() {
// Vars caching
$document = $(document);
$first = $('#first');
$second = $('#second');
$chunk = $("<div id='chunk'> truffle shuffle </div>");
documentHeight = $document.height();
animationTime = 1000;
style = {
'border':'2px solid red',
'height': documentHeight / 8,
'width': '150px'
};
style2 = {
'height': documentHeight / 4,
'width': '300px'
};
$second.hide();
}
/* ===========================================================================================================
OTHER FUNCTIONS
============================================================================================================= */
function appendChunk() {
$first.append($chunk);
$chunk.css(style);
}
function animateChunk() {
$chunk.animate(style2,animationTime,function(){
$(this).trigger('animationComplete');
});
}
/* ===========================================================================================================
INIT MODULE
============================================================================================================= */
$M.one = init;
})();
module.two.js
(function () {
// Module namespace
if (typeof $M === 'undefined') {
$M = {};
}
// Variables declaration chained
var
$second,
$chunk,
animationTime,
style;
/* ===========================================================================================================
INIT FUNCTION
============================================================================================================= */
var init = function() {
// calls setup first
setup();
// calls other functions
chunkListener();
secondListener();
isSecondVisible();
};
function setup() {
// Vars caching
$second = $('#second');
$chunk = $("#chunk");
animationTime = 1000;
style = {
'border':'2px solid red',
'height': '150px',
'width': '150px'
};
}
/* ===========================================================================================================
OTHER FUNCTIONS
============================================================================================================= */
function chunkListener() {
$chunk.on('animationComplete',function(){
$second.fadeIn().trigger('animationComplete');
});
}
function secondListener() {
$second.on('animationComplete',function(){
$chunk.animate(style,animationTime);
});
}
function isSecondVisible() {
var time = setInterval(function() {
if($second.is(':visible')) {
console.log("visible");
clearInterval(time);
} else {
$second.html("finished!");
}
},200);
}
/* ===========================================================================================================
INIT MODULE
============================================================================================================= */
$M.two = init;
})();
scope.js
$(document).ready(function () {
$M.one();
$M.two();
});
Does this pattern reminds you something already seen before?
The Modules structure is similar to the Module Pattern.
The principle of extending a "super" module that you refering to as $M
looks also familiar. See Module Augmentation
Is it a good architectural choice? Any weak points or architectural mistakes in this pattern?
Thinking Modular is often (of course depending on context, making a 'hello world' application modular is a bit an overkill) a good architectural choice. However, While reading your modules logic i was a bit doubtful about making designed in a procedural way internally and not exposing any api. I believe you have an opportunity for improving you modules design by implementing an M-V-* like architecture.
Is this a good use of IIFE functions and namespaces?
I think your usage is fine as it is. I'll perhaps add the "super" module($M
) as an argument of you modules IIFE, that should isolate better your modules from the external world (the global scope).
References