angular-from-scratch
by Antoine
HTML
<body class="container text-center">
<h1 class="page-header" ng-bind="labs.titre">Vide</h1>
<input type="text" ng-model="labs.titre"/>
</body>
JavaScript
function Scope() {
this.$$watchers = [];
}
Scope.prototype.$watch = function (watcherFn, listenerFn) {
var watcher = {
watcherFn: watcherFn,
listenerFn: listenerFn,
last: undefined
};
this.$$watchers.push(watcher);
}
Scope.prototype.$digest = function () {
var dirty;
do {
dirty = false;
_.each(this.$$watchers, function (watcher) {
var newValue = watcher.watcherFn(this);
if (watcher.last !== newValue) {
watcher.listenerFn(newValue, watcher.last, this);
watcher.last = newValue;
dirty = true;
}
}.bind(this));
} while (dirty);
}
Scope.prototype.$apply = function (exprFn) {
try {
exprFn();
} finally {
this.$digest();
}
}
var $$directives = {};
var $directive = function (name, directiveFn) {
if (directiveFn) {
$$directives[name] = directiveFn;
}
return $$directives[name];
}
var $compile = function(element, scope) {
_.each(element.children, function (child) {
$compile(child, scope);
});
_.each(element.attributes, function(attribute) {
var directiveFn = $directive(attribute.name);
if (directiveFn) {
directiveFn(scope, element, element.attributes);
}
});
}
$directive('ng-bind', function (scope, element, attributes) {
scope.$watch(function(scope) {
return eval('scope.' + attributes['ng-bind'].value);
}, function(newValue) {
element.innerHTML = newValue;
});
});
$directive('ng-model', function(scope, element, attributes) {
scope.$watch(function() {
return eval('scope.' + attributes['ng-model'].value);
}, function(newValue) {
element.value = newValue;
});
element.addEventListener('keyup', function() {
scope.$apply(function() {
eval('scope.' + attributes['ng-model'].value + ' = \"' + element.value + '\"');
});
...