aboutsummaryrefslogtreecommitdiffstats
path: root/src/directives.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/directives.js')
-rw-r--r--src/directives.js146
1 files changed, 75 insertions, 71 deletions
diff --git a/src/directives.js b/src/directives.js
index 13cd4b59..861805fe 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -1,86 +1,96 @@
-
-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);
-
+angularDirective("ng-init", function(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() {
+angularDirective("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){
- var jElement = jQuery(element);
- return function(){
- this.$watch(expression, _(jElement.attr).bind(jElement));
+angularDirective("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";
- var children = [];
+angularDirective("ng-non-bindable", function(){
+ this.descend(false);
+});
+
+angularDirective("ng-repeat", function(expression, element){
+ var reference = this.reference("ng-repeat: " + expression),
+ r = element.removeAttr('ng-repeat'),
+ template = this.compile(element),
+ match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/),
+ lhs, rhs, valueIdent, keyIdent;
+ if (! match) {
+ throw "Expected ng-repeat in form of 'item in collection' but got '" +
+ expression + "'.";
+ }
+ lhs = match[1];
+ rhs = match[2];
+ match = lhs.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/);
+ if (!match) {
+ throw "'item' in 'item in collection' should be identifier or (key, value) but got '" +
+ keyValue + "'.";
+ }
+ valueIdent = match[3] || match[1];
+ keyIdent = match[2];
+
+ var parent = element.parent();
+ element.replaceWith(reference);
return function(){
- this.$watch(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(valueIdent, value);
+ if (keyIdent) childScope.scope.set(keyIdent, key);
+ 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
//
@@ -90,7 +100,7 @@ angular.directive("non-bindable", function(expression, element){
//ng-show, ng-hide
-angular.directive("action", function(expression, element){
+angularDirective("action", function(expression, element){
return function(){
var self = this;
jQuery(element).click(function(){
@@ -99,21 +109,15 @@ angular.directive("action", function(expression, element){
};
});
-//ng-eval
-angular.directive("eval", function(expression, element){
- return function(){
- this.$onUpdate( expression);
- }
-});
//ng-watch
// <div ng-watch="$anchor.book: book=Book.get();"/>
-angular.directive("watch", function(expression, element){
+angularDirective("watch", function(expression, element){
var watches = {
'lhs':'rhs'
}; // parse
return function(){
this.$watch(watches);
- }
+ };
});
//widget related