Skip to content

Instantly share code, notes, and snippets.

@chinchang
Created December 13, 2015 07:45
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 chinchang/7563658c9281e81c5502 to your computer and use it in GitHub Desktop.
Save chinchang/7563658c9281e81c5502 to your computer and use it in GitHub Desktop.
Angular like watch and directive implementation concept using Object.observe
(function () {
function getObjectFromExpression(expr) {
var splits = expr.split('.'),
obj, propertyName;
if (splits.length === 1) {
obj = window;
propertyName = splits[0];
} else {
obj = splits.slice(0, splits.length - 1).reduce(function (obj, key) {
return obj[key];
}, window);
propertyName = splits[splits.length - 1];
}
return {
obj: obj,
propertyName: propertyName
};
};
function camelCaseToHyphen (str) {
str = str.replace(/([A-Z])/g, '-$1');
return str.toLowerCase();
}
$ = {};
$.directives = {};
$.observers = {};
$.compile = function (node) {
var i, j, k,
attributes = node.attributes;
for (var k = 0; k < attributes.length; k++) {
for (var name in this.directives) {
if (attributes[k].nodeName === this.directives[name].attrName) {
this.directives[name].init(node);
}
}
}
for (i = 0; i < node.children.length; i++) {
this.compile(node.children[i]);
}
};
$.watch = function (expr, callback) {
var propertyName, exprStuff;
try {
exprStuff = getObjectFromExpression(expr);
} catch (e) {
exprStuff = { obj: window, propertyName: '' };
}
// Add an observer on the obj
Object.observe(exprStuff.obj, function (changes) {
changes.forEach(function(change, i){
if (change.name === exprStuff.propertyName) {
callback(change.object[change.name]);
}
});
}, ['add', 'delete,', 'update']);
// Also fire the watch callback once
callback(exprStuff.obj[exprStuff.propertyName]);
}
$.registerDirective = function (name, definition) {
definition.attrName = camelCaseToHyphen(name);
this.directives[name] = definition;
};
$.boot = function (node) {
node = node || document.body;
this.compile(node)
};
// Sample ngShow Directive
$.registerDirective('ngShow', {
init: function (node) {
// TODO: Use a class to hide element instead of changing
// `display` style.
var originalDisplay = node.style.display;
$.watch(node.getAttribute('ng-show'), function (value) {
if (value) {
node.style.display = originalDisplay;
} else {
node.style.display = 'none';
}
});
}
});
window.$ = $;
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div ng-show="obj.show">
hello der
</div>
<script src="angular-with-o-o.js"></script>
<script>
var obj = { show: false };
$.boot();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment