diff options
Diffstat (limited to 'src/directives.js')
| -rw-r--r-- | src/directives.js | 146 |
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 |
