aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMisko Hevery2010-03-22 13:58:04 -0700
committerMisko Hevery2010-03-22 13:58:04 -0700
commit84552f7f8ac3f39c4dbd7d946ae2938d63302840 (patch)
treed3a4433d12bcbfb9d42f92a7b8ec12762ae7df3a /src
parentf6664ed7f6f6dd1f4f9756f57611a316089149cb (diff)
downloadangular.js-84552f7f8ac3f39c4dbd7d946ae2938d63302840.tar.bz2
got few directives working
Diffstat (limited to 'src')
-rw-r--r--src/Angular.js37
-rw-r--r--src/Compiler.js149
-rw-r--r--src/Parser.js107
-rw-r--r--src/Scope.js52
-rw-r--r--src/directives.js124
-rw-r--r--src/directivesAngularCom.js29
6 files changed, 290 insertions, 208 deletions
diff --git a/src/Angular.js b/src/Angular.js
index 8793274c..cfffab04 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -18,23 +18,32 @@ if (typeof Node == 'undefined') {
}
function noop() {}
+function identity($) {return $;}
if (!window['console']) window['console']={'log':noop, 'error':noop};
+function extension(angular, name) {
+ var extPoint;
+ return angular[name] || (extPoint = angular[name] = function (name, fn, prop){
+ if (isDefined(fn)) {
+ extPoint[name] = extend(fn, prop || {});
+ }
+ return extPoint[name];
+ });
+}
+
var consoleNode, msie,
jQuery = window['jQuery'] || window['$'], // weirdness to make IE happy
foreach = _.each,
extend = _.extend,
slice = Array.prototype.slice,
- identity = _.identity,
angular = window['angular'] || (window['angular'] = {}),
- angularValidator = angular['validator'] || (angular['validator'] = {}),
- angularDirective = angular['directive'] || (angular['directive'] = function(name, fn){
- if (fn) {angularDirective[name] = fn;};
- return angularDirective[name];
- }),
- angularFilter = angular['filter'] || (angular['filter'] = {}),
- angularFormatter = angular['formatter'] || (angular['formatter'] = {}),
- angularCallbacks = angular['callbacks'] || (angular['callbacks'] = {}),
+ angularDirective = extension(angular, 'directive'),
+ angularMarkup = extension(angular, 'markup'),
+ angularWidget = extension(angular, 'widget'),
+ angularValidator = extension(angular, 'validator'),
+ angularFilter = extension(angular, 'filter'),
+ angularFormatter = extension(angular, 'formatter'),
+ angularCallbacks = extension(angular, 'callbacks'),
angularAlert = angular['alert'] || (angular['alert'] = function(){
log(arguments); window.alert.apply(window, arguments);
});
@@ -45,7 +54,15 @@ var isVisible = isVisible || function (element) {
};
function isDefined(value){
- return typeof value !== 'undefined';
+ return typeof value != 'undefined';
+}
+
+function isObject(value){
+ return typeof value == 'object';
+}
+
+function isFunction(value){
+ return typeof value == 'function';
}
function log(a, b, c){
diff --git a/src/Compiler.js b/src/Compiler.js
index 3c757dd0..5c650204 100644
--- a/src/Compiler.js
+++ b/src/Compiler.js
@@ -13,7 +13,7 @@ function Template() {
Template.prototype = {
init: function(element, scope) {
foreach(this.inits, function(fn) {
- scope.apply(fn, nodeLite(element));
+ scope.apply(fn, jqLite(element));
});
var i,
@@ -35,8 +35,10 @@ Template.prototype = {
addChild: function(index, template) {
- this.paths.push(index);
- this.children.push(template);
+ if (template) {
+ this.paths.push(index);
+ this.children.push(template);
+ }
},
empty: function() {
@@ -45,31 +47,37 @@ Template.prototype = {
};
///////////////////////////////////
-//NodeLite
+//JQLite
//////////////////////////////////
-function NodeLite(element) {
+function JQLite(element) {
this.element = element;
}
-function nodeLite(element) {
- return element instanceof NodeLite ? element : new NodeLite(element);
+function jqLite(element) {
+ if (typeof element == 'string') {
+ var div = document.createElement('div');
+ div.innerHTML = element;
+ element = div.childNodes[0];
+ }
+ return element instanceof JQLite ? element : new JQLite(element);
}
-NodeLite.prototype = {
+JQLite.prototype = {
eachTextNode: function(fn){
var i, chldNodes = this.element.childNodes || [], size = chldNodes.length, chld;
for (i = 0; i < size; i++) {
- if((chld = new NodeLite(chldNodes[i])).isText()) {
+ if((chld = new JQLite(chldNodes[i])).isText()) {
fn(chld, i);
}
}
},
+
eachNode: function(fn){
var i, chldNodes = this.element.childNodes || [], size = chldNodes.length, chld;
for (i = 0; i < size; i++) {
- if(!(chld = new NodeLite(chldNodes[i])).isText()) {
+ if(!(chld = new JQLite(chldNodes[i])).isText()) {
fn(chld, i);
}
}
@@ -84,34 +92,51 @@ NodeLite.prototype = {
},
replaceWith: function(replaceNode) {
- this.element.parentNode.replaceChild(nodeLite(replaceNode).element, this.element);
+ this.element.parentNode.replaceChild(jqLite(replaceNode).element, this.element);
},
- removeAttribute: function(name) {
+ remove: function() {
+ this.element.parentNode.removeChild(this.element);
+ },
+
+ removeAttr: function(name) {
this.element.removeAttribute(name);
},
after: function(element) {
- this.element.parentNode.insertBefore(nodeLite(element).element, this.element.nextSibling);
+ this.element.parentNode.insertBefore(jqLite(element).element, this.element.nextSibling);
},
attr: function(name, value){
- if (isDefined(value)) {
- this.element.setAttribute(name, value);
+ var e = this.element;
+ if (isObject(name)) {
+ foreach(name, function(value, name){
+ e.setAttribute(name, value);
+ });
+ } else if (isDefined(value)) {
+ e.setAttribute(name, value);
} else {
- return this.element.getAttribute(name);
+ return e.getAttribute(name);
}
},
text: function(value) {
if (isDefined(value)) {
- this.element.nodeValue = value;
+ this.element.textContent = value;
}
- return this.element.nodeValue;
+ return this.element.textContent;
},
+ html: function(value) {
+ if (isDefined(value)) {
+ this.element.innerHTML = value;
+ }
+ return this.element.innerHTML;
+ },
+
+ parent: function() { return jqLite(this.element.parentNode);},
isText: function() { return this.element.nodeType == Node.TEXT_NODE; },
- clone: function() { return nodeLite(this.element.cloneNode(true)); }
+ clone: function() { return jqLite(this.element.cloneNode(true)); }
};
///////////////////////////////////
@@ -124,14 +149,14 @@ function Compiler(markup, directives, widgets){
this.widgets = widgets;
}
-DIRECTIVE = /^ng-(.*)$/;
-
Compiler.prototype = {
- compile: function(element) {
- var template = this.templetize(nodeLite(element)) || new Template();
- return function(element){
- var scope = new Scope();
+ compile: function(rawElement) {
+ rawElement = jqLite(rawElement);
+ var template = this.templatize(rawElement) || new Template();
+ return function(element, parentScope){
+ var scope = new Scope(parentScope);
scope.element = element;
+ // todo return should be a scope with everything already set on it as element
return {
scope: scope,
element:element,
@@ -140,57 +165,57 @@ Compiler.prototype = {
};
},
- templetize: function(element){
+ templatize: function(element){
var self = this,
+ elementName = element.element.nodeName,
+ widgets = self.widgets,
+ widget = widgets[elementName],
markup = self.markup,
markupSize = markup.length,
directives = self.directives,
- widgets = self.widgets,
- recurse = true,
+ descend = true,
exclusive = false,
directiveQueue = [],
- template = new Template();
-
- // process markup for text nodes only
- element.eachTextNode(function(textNode){
- for (var i = 0, text = textNode.text(); i < markupSize; i++) {
- markup[i].call(self, text, textNode, element);
- }
- });
+ template = new Template(),
+ selfApi = {
+ compile: bind(self, self.compile),
+ reference:function(name) {return jqLite(document.createComment(name));},
+ descend: function(value){ if(isDefined(value)) descend = value; return descend;}
+ };
+
+ if (widget) {
+ template.addInit(widget.call(selfApi, element));
+ } else {
+ // process markup for text nodes only
+ element.eachTextNode(function(textNode){
+ for (var i = 0, text = textNode.text(); i < markupSize; i++) {
+ markup[i].call(selfApi, text, textNode, element);
+ }
+ });
- // Process attributes/directives
- element.eachAttribute(function(name, value){
- var match = name.match(DIRECTIVE),
- directive;
- if (!exclusive && match) {
- directive = directives[match[1]];
- if (directive) {
+ // Process attributes/directives
+ element.eachAttribute(function(name, value){
+ var directive = directives[name];
+ if (!exclusive && directive) {
if (directive.exclusive) {
exclusive = true;
directiveQueue = [];
}
- directiveQueue.push(bind(self, directive, value, element));
- } else {
- error("Directive '" + match[0] + "' is not recognized.");
+ directiveQueue.push(bind(selfApi, directive, value, element));
}
- }
- });
-
- // Execute directives
- foreach(directiveQueue, function(directive){
- var init = directive();
- template.addInit(init);
- recurse = recurse && init;
- });
+ });
- // Process non text child nodes
- if (recurse) {
- element.eachNode(function(child, i){
- var childTemplate = self.templetize(child);
- if(childTemplate) {
- template.addChild(i, childTemplate);
- }
+ // Execute directives
+ foreach(directiveQueue, function(directive){
+ template.addInit(directive());
});
+
+ // Process non text child nodes
+ if (descend) {
+ element.eachNode(function(child, i){
+ template.addChild(i, self.templatize(child));
+ });
+ }
}
return template.empty() ? null : template;
}
diff --git a/src/Parser.js b/src/Parser.js
index b59b21a7..c18a6250 100644
--- a/src/Parser.js
+++ b/src/Parser.js
@@ -40,7 +40,7 @@ Lexer.prototype = {
return false;
}
},
-
+
parse: function() {
var tokens = this.tokens;
var OPERATORS = Lexer.OPERATORS;
@@ -103,22 +103,22 @@ Lexer.prototype = {
}
return tokens;
},
-
+
isNumber: function(ch) {
return '0' <= ch && ch <= '9';
},
-
+
isWhitespace: function(ch) {
return ch == ' ' || ch == '\r' || ch == '\t' ||
ch == '\n' || ch == '\v';
},
-
+
isIdent: function(ch) {
return 'a' <= ch && ch <= 'z' ||
'A' <= ch && ch <= 'Z' ||
'_' == ch || ch == '$';
},
-
+
readNumber: function() {
var number = "";
var start = this.index;
@@ -135,7 +135,7 @@ Lexer.prototype = {
this.tokens.push({index:start, text:number,
fn:function(){return number;}});
},
-
+
readIdent: function() {
var ident = "";
var start = this.index;
@@ -157,15 +157,17 @@ Lexer.prototype = {
}
this.tokens.push({index:start, text:ident, fn:fn});
},
-
+
readString: function(quote) {
var start = this.index;
var dateParseLength = this.dateParseLength;
this.index++;
var string = "";
+ var rawString = quote;
var escape = false;
while (this.index < this.text.length) {
var ch = this.text.charAt(this.index);
+ rawString += ch;
if (escape) {
if (ch == 'u') {
var hex = this.text.substring(this.index + 1, this.index + 5);
@@ -184,7 +186,7 @@ Lexer.prototype = {
escape = true;
} else if (ch == quote) {
this.index++;
- this.tokens.push({index:start, text:string,
+ this.tokens.push({index:start, text:rawString, string:string,
fn:function(){
return (string.length == dateParseLength) ?
angular['String']['toDate'](string) : string;
@@ -199,7 +201,7 @@ Lexer.prototype = {
this.text.substring(start) + "] starting at column '" +
(start+1) + "' in expression '" + this.text + "'.";
},
-
+
readRegexp: function(quote) {
var start = this.index;
this.index++;
@@ -249,18 +251,18 @@ Parser.ZERO = function(){
Parser.prototype = {
error: function(msg, token) {
- throw "Token '" + token.text +
- "' is " + msg + " at column='" +
- (token.index + 1) + "' of expression '" +
+ throw "Token '" + token.text +
+ "' is " + msg + " at column='" +
+ (token.index + 1) + "' of expression '" +
this.text + "' starting at '" + this.text.substring(token.index) + "'.";
},
-
+
peekToken: function() {
- if (this.tokens.length === 0)
+ if (this.tokens.length === 0)
throw "Unexpected end of expression: " + this.text;
return this.tokens[0];
},
-
+
peek: function(e1, e2, e3, e4) {
var tokens = this.tokens;
if (tokens.length > 0) {
@@ -273,7 +275,7 @@ Parser.prototype = {
}
return false;
},
-
+
expect: function(e1, e2, e3, e4){
var token = this.peek(e1, e2, e3, e4);
if (token) {
@@ -283,7 +285,7 @@ Parser.prototype = {
}
return false;
},
-
+
consume: function(e1){
if (!this.expect(e1)) {
var token = this.peek();
@@ -293,30 +295,30 @@ Parser.prototype = {
this.text.substring(token.index) + "'.";
}
},
-
+
_unary: function(fn, right) {
return function(self) {
return fn(self, right(self));
};
},
-
+
_binary: function(left, fn, right) {
return function(self) {
return fn(self, left(self), right(self));
};
},
-
+
hasTokens: function () {
return this.tokens.length > 0;
},
-
+
assertAllConsumed: function(){
if (this.tokens.length !== 0) {
throw "Did not understand '" + this.text.substring(this.tokens[0].index) +
"' while evaluating '" + this.text + "'.";
}
},
-
+
statements: function(){
var statements = [];
while(true) {
@@ -335,7 +337,7 @@ Parser.prototype = {
}
}
},
-
+
filterChain: function(){
var left = this.expression();
var token;
@@ -347,15 +349,15 @@ Parser.prototype = {
}
}
},
-
+
filter: function(){
return this._pipeFunction(angularFilter);
},
-
+
validator: function(){
return this._pipeFunction(angularValidator);
},
-
+
_pipeFunction: function(fnScope){
var fn = this.functionIdent(fnScope);
var argsFn = [];
@@ -373,7 +375,7 @@ Parser.prototype = {
var _this = this;
foreach(self, function(v, k) {
if (k.charAt(0) == '$') {
- _this[k] = v;
+ _this[k] = v;
}
});
};
@@ -386,11 +388,11 @@ Parser.prototype = {
}
}
},
-
+
expression: function(){
return this.throwStmt();
},
-
+
throwStmt: function(){
if (this.expect('throw')) {
var throwExp = this.assignment();
@@ -401,7 +403,7 @@ Parser.prototype = {
return this.assignment();
}
},
-
+
assignment: function(){
var left = this.logicalOR();
var token;
@@ -417,7 +419,7 @@ Parser.prototype = {
return left;
}
},
-
+
logicalOR: function(){
var left = this.logicalAND();
var token;
@@ -429,7 +431,7 @@ Parser.prototype = {
}
}
},
-
+
logicalAND: function(){
var left = this.equality();
var token;
@@ -438,7 +440,7 @@ Parser.prototype = {
}
return left;
},
-
+
equality: function(){
var left = this.relational();
var token;
@@ -447,7 +449,7 @@ Parser.prototype = {
}
return left;
},
-
+
relational: function(){
var left = this.additive();
var token;
@@ -456,7 +458,7 @@ Parser.prototype = {
}
return left;
},
-
+
additive: function(){
var left = this.multiplicative();
var token;
@@ -465,7 +467,7 @@ Parser.prototype = {
}
return left;
},
-
+
multiplicative: function(){
var left = this.unary();
var token;
@@ -474,7 +476,7 @@ Parser.prototype = {
}
return left;
},
-
+
unary: function(){
var token;
if (this.expect('+')) {
@@ -487,7 +489,7 @@ Parser.prototype = {
return this.primary();
}
},
-
+
functionIdent: function(fnScope) {
var token = this.expect();
var element = token.text.split('.');
@@ -504,7 +506,7 @@ Parser.prototype = {
}
return instance;
},
-
+
primary: function() {
var primary;
if (this.expect('(')) {
@@ -540,7 +542,7 @@ Parser.prototype = {
}
return primary;
},
-
+
closure: function(hasArgs) {
var args = [];
if (hasArgs) {
@@ -566,7 +568,7 @@ Parser.prototype = {
};
};
},
-
+
fieldAccess: function(object) {
var field = this.expect().text;
var fn = function (self){
@@ -575,7 +577,7 @@ Parser.prototype = {
fn.isAssignable = field;
return fn;
},
-
+
objectIndex: function(obj) {
var indexFn = this.expression();
this.consume(']');
@@ -592,7 +594,7 @@ Parser.prototype = {
};
}
},
-
+
functionCall: function(fn) {
var argsFn = [];
if (this.peekToken().text != ')') {
@@ -614,7 +616,7 @@ Parser.prototype = {
}
};
},
-
+
// This is used with json array declaration
arrayDeclaration: function () {
var elementFns = [];
@@ -632,12 +634,13 @@ Parser.prototype = {
return array;
};
},
-
+
object: function () {
var keyValues = [];
if (this.peekToken().text != '}') {
do {
- var key = this.expect().text;
+ var token = this.expect(),
+ key = token.string || token.text;
this.consume(":");
var value = this.expression();
keyValues.push({key:key, value:value});
@@ -654,7 +657,7 @@ Parser.prototype = {
return object;
};
},
-
+
entityDeclaration: function () {
var decl = [];
while(this.hasTokens()) {
@@ -671,7 +674,7 @@ Parser.prototype = {
return code;
};
},
-
+
entityDecl: function () {
var entity = this.expect().text;
var instance;
@@ -690,16 +693,16 @@ Parser.prototype = {
var document = Entity();
document['$$anchor'] = instance;
self.scope.set(instance, document);
- return "$anchor." + instance + ":{" +
+ return "$anchor." + instance + ":{" +
instance + "=" + entity + ".load($anchor." + instance + ");" +
- instance + ".$$anchor=" + angular['String']['quote'](instance) + ";" +
+ instance + ".$$anchor=" + angular['String']['quote'](instance) + ";" +
"};";
} else {
return "";
}
};
},
-
+
watch: function () {
var decl = [];
while(this.hasTokens()) {
@@ -716,7 +719,7 @@ Parser.prototype = {
}
};
},
-
+
watchDecl: function () {
var anchorName = this.expect().text;
this.consume(":");
diff --git a/src/Scope.js b/src/Scope.js
index 3633f960..d22604fd 100644
--- a/src/Scope.js
+++ b/src/Scope.js
@@ -1,18 +1,23 @@
function Scope(initialState, name) {
- this.widgets = [];
- this.evals = [];
- this.watchListeners = {};
- this.name = name;
+ var self = this;
+ self.widgets = [];
+ self.evals = [];
+ self.watchListeners = {};
+ self.name = name;
initialState = initialState || {};
var State = function(){};
State.prototype = initialState;
- this.state = new State();
- this.state['$parent'] = initialState;
+ self.state = new State();
+ extend(self.state, {
+ '$parent': initialState,
+ '$watch': bind(self, self.addWatchListener),
+ '$eval': bind(self, self.eval),
+ // change name to onEval?
+ '$addEval': bind(self, self.addEval)
+ });
if (name == "ROOT") {
- this.state['$root'] = this.state;
+ self.state['$root'] = self.state;
}
- this.set('$watch', bind(this, this.addWatchListener));
- this.set('$eval', bind(this, this.addEval));
};
Scope.expressionCache = {};
@@ -47,6 +52,7 @@ Scope.getter = function(instance, path) {
};
Scope.prototype = {
+ // TODO: rename to update? or eval?
updateView: function() {
var self = this;
this.fireWatchers();
@@ -64,7 +70,13 @@ Scope.prototype = {
addEval: function(fn, listener) {
// todo: this should take a function/string and a listener
- this.evals.push(fn);
+ // todo: this is a hack, which will need to be cleaned up.
+ var self = this,
+ listenFn = listener || noop,
+ expr = bind(self, self.compile(fn), {scope: self, self: self.state});
+ this.evals.push(function(){
+ self.apply(listenFn, expr());
+ });
},
isProperty: function(exp) {
@@ -103,15 +115,21 @@ Scope.prototype = {
this.eval(expressionText + "=" + toJson(value));
},
- eval: function(expressionText, context) {
-// log('Scope.eval', expressionText);
- var expression = Scope.expressionCache[expressionText];
- if (!expression) {
- var parser = new Parser(expressionText);
- expression = parser.statements();
+ compile: function(exp) {
+ if (isFunction(exp)) return exp;
+ var expFn = Scope.expressionCache[exp];
+ if (!expFn) {
+ var parser = new Parser(exp);
+ expFn = parser.statements();
parser.assertAllConsumed();
- Scope.expressionCache[expressionText] = expression;
+ Scope.expressionCache[exp] = expFn;
}
+ return expFn;
+ },
+
+ eval: function(expressionText, context) {
+// log('Scope.eval', expressionText);
+ var expression = this.compile(expressionText);
context = context || {};
context.scope = this;
context.self = this.state;
diff --git a/src/directives.js b/src/directives.js
index 26cbfe2c..66a5e864 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -1,86 +1,82 @@
-
-angular.directive("auth", function(expression, element){
+angularDirective("ng-init", function(expression){
return function(){
- if(expression == "eager") {
- this.$users.fetchCurrent();
- }
- };
-});
-
-
-//expression = "book=Book:{year=2000}"
-angular.directive("entity", function(expression, element){
- //parse expression, ignore element
- var entityName; // "Book";
- var instanceName; // "book";
- var defaults; // {year: 2000};
-
- parse(expression);
-
- return function(){
- this[entityName] = this.$datastore.entity(entityName, defaults);
- this[instanceName] = this[entityName]();
- this.$watch("$anchor."+instanceName, function(newAnchor){
- this[instanceName] = this[entityName].get(this.$anchor[instanceName]);
- });
+ this.$eval(expression);
};
});
-
-angular.directive("init", function(expression, element){
+angularDirective("ng-eval", function(expression){
return function(){
- this.$eval(expresssion);
+ this.$addEval(expression);
};
});
-
-//translation of {{ }} to ng-bind is external to this
-angular.directive("bind", function(expression, element){
- return function() {
+angular.directive("ng-bind", function(expression){
+ return function(element) {
this.$watch(expression, function(value){
- element.innerText = value;
+ element.text(value);
});
};
});
-
-// translation of {{ }} to ng-bind-attr is external to this
-// <a href="http://example.com?id={{book.$id}}" alt="{{book.$name}}">link</a>
-// becomes
-// <a href="" ng-bind-attr="{href:'http://example.com?id={{book.$id}}', alt:'{{book.$name}}'}">link</a>
-angular.directive("bind-attr", function(expression, element){
- return function(expression, element){
- var jElement = jQuery(element);
- this.$watch(expression, _(jElement.attr).bind(jElement));
+angular.directive("ng-bind-attr", function(expression){
+ return function(element){
+ this.$watch(expression, bind(element, element.attr));
};
});
-angular.directive("repeat", function(expression, element){
- var anchor = document.createComment(expression);
- jQuery(element).replace(anchor);
- var template = this.compile(element);
- var lhs = "item";
- var rhs = "items";
+angular.directive("ng-non-bindable", function(){
+ this.descend(false);
+});
+
+angular.directive("ng-repeat", function(expression, element){
+ var reference = this.reference("ng-repeat: " + expression),
+ r = element.removeAttr('ng-repeat'),
+ template = this.compile(element),
+ path = expression.split(' in '),
+ lhs = path[0],
+ rhs = path[1];
+ var parent = element.parent();
+ element.replaceWith(reference);
return function(){
- var children = [];
- this.$eval(rhs, function(items){
- foreach(children, function(child){
- child.element.remove();
- });
- foreach(items, function(item){
- var child = template(item); // create scope
- element.addChild(child.element, anchor);
- children.push(child);
+ var children = [],
+ currentScope = this;
+ this.$addEval(rhs, function(items){
+ var index = 0, childCount = children.length, childScope, lastElement = reference;
+ foreach(items, function(value, key){
+ if (index < childCount) {
+ // reuse existing child
+ childScope = children[index];
+ } else {
+ // grow children
+ childScope = template(element.clone(), currentScope);
+ childScope.init();
+ childScope.scope.set('$index', index);
+ childScope.element.attr('ng-index', index);
+ lastElement.after(childScope.element);
+ children.push(childScope);
+ }
+ childScope.scope.set(lhs, value);
+ childScope.scope.updateView();
+ lastElement = childScope.element;
+ index ++;
});
+ // shrink children
+ while(children.length > index) {
+ children.pop().element.remove();
+ }
});
};
-});
+}, {exclusive: true});
+
+
+/////////////////////////////////////////
+/////////////////////////////////////////
+/////////////////////////////////////////
+/////////////////////////////////////////
+/////////////////////////////////////////
+
-//ng-non-bindable
-angular.directive("non-bindable", function(expression, element){
- return false;
-});
//Styling
//
@@ -99,12 +95,6 @@ angular.directive("action", function(expression, element){
};
});
-//ng-eval
-angular.directive("eval", function(expression, element){
- return function(){
- this.$eval(expression);
- };
-});
//ng-watch
// <div ng-watch="$anchor.book: book=Book.get();"/>
angular.directive("watch", function(expression, element){
diff --git a/src/directivesAngularCom.js b/src/directivesAngularCom.js
new file mode 100644
index 00000000..84032bdd
--- /dev/null
+++ b/src/directivesAngularCom.js
@@ -0,0 +1,29 @@
+
+angular.directive("auth", function(expression, element){
+ return function(){
+ if(expression == "eager") {
+ this.$users.fetchCurrent();
+ }
+ };
+});
+
+
+//expression = "book=Book:{year=2000}"
+angular.directive("entity", function(expression, element){
+ //parse expression, ignore element
+ var entityName; // "Book";
+ var instanceName; // "book";
+ var defaults; // {year: 2000};
+
+ parse(expression);
+
+ return function(){
+ this[entityName] = this.$datastore.entity(entityName, defaults);
+ this[instanceName] = this[entityName]();
+ this.$watch("$anchor."+instanceName, function(newAnchor){
+ this[instanceName] = this[entityName].get(this.$anchor[instanceName]);
+ });
+ };
+});
+
+