Skip to content

Instantly share code, notes, and snippets.

@exogen
Created March 17, 2011 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save exogen/874715 to your computer and use it in GitHub Desktop.
Save exogen/874715 to your computer and use it in GitHub Desktop.
Basic Knockout functionality in 100 lines
ko = {};
ko.Observable = function(value) {
this.value = value;
this.subscribers = [];
};
ko.Observable.prototype.get = function() {
return this.value;
};
ko.Observable.prototype.set = function(value) {
this.value = value;
this.notifySubscribers(value);
};
ko.Observable.prototype.subscribe = function(callback) {
this.subscribers.push(callback);
};
ko.Observable.prototype.notifySubscribers = function(value) {
for (var i = 0; i < this.subscribers.length; i++) {
var subscriber = this.subscribers[i];
subscriber(value);
}
};
ko.unwrapObservable = function(value) {
while (value instanceof ko.Observable) {
value = value.get();
}
return value;
}
ko.applyBindings = function(model, scope) {
if (typeof scope == 'undefined')
scope = document.body;
var elements = $('[data-bind]', scope);
for (var i = 0; i < elements.length; i++) {
var element = $(elements[i]);
var attrValue = element.attr('data-bind');
var bindings = ko.parseBindings(attrValue, model);
// Apply handlers, subscribing if necessary.
ko.bindElement(element, bindings, model);
}
};
ko.parseBindings = function(string, model) {
var bindings = {};
with (model) {
// Evaluate `string` in the context of `model`
bindings = eval('new Object({' + string + '});');
}
return bindings;
}
ko.bindElement = function(element, bindings, model) {
for (name in bindings) {
var value = bindings[name];
var handler = ko.bindingHandlers[name];
// Ignore undefined handlers
if (typeof handler != 'undefined') { // Ignore undefined handlers
// Call the handler's init function once
if (typeof handler.init == 'function') {
handler.init.call(model, element, value);
}
if (typeof handler.update == 'function') {
// Call the handler's update function once...
handler.update.call(model, element, value);
if (value instanceof ko.Observable) {
// ...and subscribe to it if `value` is observable
value.subscribe(function(value) {
handler.update.call(model, element, value);
});
}
}
}
}
};
ko.bindingHandlers = {};
ko.bindingHandlers.text = {
update: function(element, value) {
element.text(ko.unwrapObservable(value));
}
};
ko.bindingHandlers.value = {
init: function(element, value) {
element.change(function() {
value.set(this.value);
});
},
update: function(element, value) {
element[0].value = ko.unwrapObservable(value);
}
};
@statico
Copy link

statico commented Mar 19, 2011

Found this randomly through a Google search. Interesting :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment