(function() { "use strict"; var view, viewModel, valueTemplate; valueTemplate = { configurable: false, enumerable: true, get: function() { return this._value; }, set: function(val) { var i; if (val !== this._value) { this._value = val; for (i = 0; i < this._listeners.length; i += 1) { this._listeners[i](); } if (this.onChange) { this.onChange(); } } } }; // this is simply data and behavior. In this // case a single property is tracked with an // event fired when it changes function ViewModel() { this._listeners = []; this._value = ""; } Object.defineProperty(ViewModel.prototype, "text", valueTemplate); ViewModel.prototype.attach = function(fn) { this._listeners.push(fn); }; // this is a data-binder for input boxes function InputBinder(elem) { var that = this; this._listeners = []; this._elem = elem; elem.onkeyup = function() { that.value = elem.value; }; } InputBinder.prototype.attach = function(fn) { this._listeners.push(fn); } InputBinder.prototype.onChange = function() { this._elem.value = this.value; }; Object.defineProperty(InputBinder.prototype, "value", valueTemplate); // this is a data-binder for divs function DivBinder(elem) { this._listeners = []; this._elem = elem; } DivBinder.prototype.attach = function(fn) { this._listeners.push(fn); } DivBinder.prototype.onChange = function() { this._elem.innerText = this.value; }; Object.defineProperty(DivBinder.prototype, "value", valueTemplate); // the view simply attaches the data-bindings function View(viewModel, ui) { var inputBinder = new InputBinder( ui.getElementsByTagName("input")[0]), divBinder = new DivBinder( ui.getElementsByTagName("div")[0]); viewModel.attach(function() { divBinder.value = viewModel.text; }); inputBinder.attach(function() { viewModel.text = inputBinder.value; }); } viewModel = new ViewModel(); view = new View(viewModel, document.getElementById('myApp')); viewModel.text = "Ready."; })();
<div id="myApp"> <label for="inputBox">Type Something:</label> <input name="inputBox"/> <div id="output"> Output Will Appear Here </div> </div>