var Observable = function() { var events = {}; this.on = function(name, func) { if (!events[name]) events[name] = []; events[name].push(func); }; this.trigger = function(name, data) { if (events[name] && events[name].length > 0) { for (var i = 0, l = events[name].length; i < l; i++) { events[name][i].call(this, data); } } }; this.off = function(name, func) { var l = arguments.length; if (l == 0) { events = {}; } else if (l == 1 && events[name]) { delete events[name]; } else if (l == 2 && events[name] && events[name].length > 0) { for (var i = 0, _l = events[name].length; i < _l; i++) { if (events[name][i] == func) { delete events[name][i]; return; } } } } }; var MVVM = { value: function(def) { var self = this; var _value; var setter = function(value) { _value = value || def; self.trigger('change:model', { value: value }); }; setter.toString = function() { return _value || def; }; return setter; } }; Observable.call(MVVM); MVVM.on('change:model', function() { Array.prototype.slice.call(document.querySelectorAll('[data-bind]')).forEach(function(el) { var boundData = eval('({' + el.dataset.bind + '})'); for (var prop in boundData) { var value = boundData[prop]; el[prop] = typeof value == 'object' ? function(prop, val) { for (var v in val) { prop[v] = val[v]; } }(el[prop], value) : value; MVVM.trigger('change:view'); } }); }); MVVM.apply = function() { MVVM.trigger('change:model'); }; var color = MVVM.value('red'); var fatih = MVVM.value('fath'); MVVM.apply();
<div data-bind="innerHTML: fatih, style: {color: color}, onclick: function() {fatih('hi!')}"></div> <div data-bind="innerText: fatih, style: {display: function() {return fatih == 'hi!'?'none':'block'}()}"></div>