This question is an improvement I did based on recommendations from this other question: Simple object-oriented calculator
var Base = function (self) {
// base class initialization
self = self || {};
self.override = function(method, body) {
var overriden = self[method];
self[method] = body;
self[method].superior = overriden;
}
return self;
};
var ViewBase = function(self) {
self = Base(self);
self.parse = function() {
keys = Array('parse').concat(Object.keys(Base()));
for(prop in self) {
if (_.contains(keys, prop)) continue;
var name = _.camelCase(prop);
self[name] = $('#' + self[prop]);
}
};
self.parse();
return self;
};
// View class mirroring html components
var ViewCalc = function() {
self = {};
self.IPT_X = 'x';
self.IPT_Y = 'y';
self.IPT_RES = 'res';
self.BTN_SUM = 'sum';
self.BTN_SUBTRACT = 'subt';
self.BTN_MULTIPLY = 'mult';
self.BTN_DIVISION = 'div';
self.BTN_CLEAN = 'clean';
self.BTN_RAND = 'rand';
return ViewBase(self);
};
var Operands = function (self) {
self = Base(self);
// connect view to the base business class
self.view = ViewCalc(self);
//public
self.x = 0;
self.y = 0;
//public
self.showOperands = function() {
//use of a private property (IPT_yyX) and a public property (this.x)
self.view.iptX.val(self.x);
self.view.iptY.val(self.y);
};
self.clean = function() {
self.x = 0;
self.y = 0;
// call to a local public method
self.showOperands();
};
self.updateOperands = function(_x, _y) {
// use of a public property
self.x = _x;
self.y = _y;
};
self.clean();
return self;
};
var Randomizer = function(self) {
self = Operands(self);
// private
function getRandomNumber() {
return Math.round(Math.random() * 1000);
};
self.override('updateOperands', function(_x, _y) {
// call to superior class's method
self.updateOperands.superior(_x, _y);
// call to method of superior object
self.showOperands();
});
self.populateRandomNumbers = function() {
// call to public local method (this.updateOperands())
// and to a local private method (getRandomNumber()))
self.updateOperands(getRandomNumber(), getRandomNumber());
};
// init
self.populateRandomNumbers();
return self;
};
var Operations = function(self) {
self = Randomizer(self);
// private
function doSum() {
return self.x + self.y;
};
function doSubtraction() {
return self.x - self.y;
};
function doMultiplication() {
return self.x * self.y;
};
function doDivision() {
return self.x / self.y;
};
function showRes(val) {
self.view.iptRes.val(val);
};
//public
self.sum = function() {
// call to 2 local private methods
showRes(doSum());
};
self.subtract = function() {
showRes(doSubtraction());
};
self.multiply = function() {
showRes(doMultiplication());
};
self.division = function() {
showRes(doDivision());
};
// init
self.view.btnSum.on('click', function() { self.sum() });
self.view.btnSubtract.on('click', function() { self.subtract() });
self.view.btnMultiply.on('click', function() { self.multiply() });
self.view.btnDivision.on('click', function() { self.division() });
self.view.btnClean.on('click', function() { self.clean() });
self.view.btnRand.on('click', function() { self.populateRandomNumbers() });
return self;
};
var o = Operations();
<html>
<body>
X: <input id='x'>
<br>
Y: <input id='y'>
<br>
Res: <input id='res'>
<br>
<input id='sum' type='button' value='+'>
<input id='subt' type='button' value='-'>
<input id='mult' type='button' value='*'>
<input id='div' type='button' value='/'>
<input id='clean' type='button' value='C'>
<input id='rand' type='button' value='Rand'>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="base.js"></script>
<script type="text/javascript" src="viewBase.js"></script>
<script type="text/javascript" src="viewCalc.js"></script>
<script type="text/javascript" src="operands.js"></script>
<script type="text/javascript" src="randomizer.js"></script>
<script type="text/javascript" src="operations.js"></script>
What I did:
From @tkellehe's recommendations:
- Separated the view part in a class of it's own. Now it has its own base class, and I can automatically create the jQuery object's properties. No need to declare them.
- Create function 'override'. Now I can call higher hierarchy classes' methods.
- Used one of the 'Big Names' library to create the jQuery object's properties: Lodash.
From @Flambino's recommendations:
- Converted IIFEs to normal functions and did inheritance as recommended.
- Changed Operators name to Operands. It's really a more correct name.
- Removed Math dependency. It wasn't really needed.
From @tkellehe's and @Flambino's recommendations:
- Self always comes first now.
- I didn't put all inside a big function because in the actual code I'm developing in my computer each class is in a separate file. I just put everything together here in order to work on the site. And I also intend to use Require.js for code. So I guess this is kind difficult to do with it. Or maybe you can imagine some way of doing it?
From @Quill - HAT MANIAC's recommendations:
calcSomething
functions where renameddoSomething
functions. I wanted to express that the 'operation' function is the function directly connected to the control and the 'doOperation' function is the 'business rules' function.
What do you think of my modifications? Are they better?
I (hopefully) improved the code and created another question here: