Spoilers!!
(duh..)
This code manipulates two HTML number input controls and multiplies them.
I am trying my luck on implementing MVC in JavaScript by example. This is a very minimal and useless code! What I am doing is achievable directly; by listening to the "change" or "input" event number-input fires. And here I am bloating code in order to learn. What a waste of time, ours, combined.
Anyway, here I am and here you are: gist | jsfiddle
function Event() {
this.listeners = []
}
Event.prototype = {
attach: function(listener) {
this.listeners.push(listener)
},
notify: function(args) {
this.listeners.forEach(function(l) {
l(args)
})
}
}
function Model(numberValue, timesValue) {
this.numberValue = numberValue
this.timesValue = timesValue
this.numberUpdated = new Event()
this.timesUpdated = new Event()
var self = this
this.changeNumber = function(number) {
self.numberValue = number
self.numberUpdated.notify()
}
this.changeTimes = function(times) {
self.timesValue = times
self.timesUpdated.notify()
}
this.getNumber = function() {
return self.numberValue
}
this.getTimes = function() {
return self.timesValue
}
}
function View(model, elements) {
this.model = model
this.elements = elements
this.numberChanged = new Event()
this.timesChanged = new Event()
var self = this
this.model.numberUpdated.attach(function() {
self.recalculate()
})
this.model.timesUpdated.attach(function() {
self.recalculate()
})
this.elements.number.addEventListener('input', function() {
self.numberChanged.notify({
value: self.elements.number.value
})
})
this.elements.times.addEventListener('input', function() {
self.timesChanged.notify({
value: self.elements.times.value
})
})
this.recalculate = function() {
self.elements.result.innerHTML = self.model.getNumber() * self.model.getTimes()
}
this.show = function() {
self.elements.number.value = self.model.getNumber()
self.elements.times.value = self.model.getTimes()
self.recalculate()
}
}
function Controller(model, view) {
this.model = model
this.view = view
var self = this
this.view.numberChanged.attach(function() {
self.model.changeNumber(self.view.elements.number.value)
})
this.view.timesChanged.attach(function() {
self.model.changeTimes(self.view.elements.times.value)
})
}
function run() {
var number = document.getElementById('number')
var times = document.getElementById('times')
var result = document.getElementById('result')
var model = new Model(9, 0.987654321)
var elements = {
number: number,
times: times,
result: result
}
var view = new View(model, elements)
var controller = new Controller(model, view)
view.show()
}
run()
#result,
input[type="number"] {
padding: 4px;
font-size: 16px;
background-color: transparent;
border: none;
text-align: center;
display: inline-block;
}
<div>
Try changing the numbers. Use buttons. OR you know what, enter a number.
</div>
<input type="number" id="number" value="3">*
<input type="number" id="times" value="3">= <span id="result"></span>
As of right now, I am very happy that I got this working. It's an achievement for me. Really! And I know this code is bad, somehow; I cannot shake the feeling. (cue Max Payne music)
I knew it when I started writing code, I knew it in my gut that something was off; I was tired, I could have stopped, I didn't. I had to find out what will be wrong with the code.
What is this code missing? What makes it less of an MVC implementation?