From c5b2bf083c7044aaf9269ad2cd6469fd14653917 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Wed, 10 Nov 2010 16:14:47 -0800 Subject: Make ng:repeat expose $position. - $position is a textual representation of the position of repeated item ('first', 'middle', 'last') - added specs for $index --- src/directives.js | 28 ++++++++++++++-- test/directivesSpec.js | 89 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 88 insertions(+), 29 deletions(-) diff --git a/src/directives.js b/src/directives.js index 24b85908..50901cbe 100644 --- a/src/directives.js +++ b/src/directives.js @@ -434,6 +434,10 @@ angularWidget("@ng:non-bindable", noop); * scope expression giving the collection to enumerate. * For example: `(name, age) in {'adam':10, 'amalie':12}`. * + * Special properties set on the local scope: + * * {number} $index - iterator offset of the repeated element (0..length-1) + * * {string} $position - position of the repeated element in the iterator ('first', 'middle', 'last') + * * @exampleDescription * This example initializes the scope to a list of names and * than uses `ng:repeat` to display every person. @@ -477,9 +481,24 @@ angularWidget("@ng:repeat", function(expression, element){ var children = [], currentScope = this; this.$onEval(function(){ - var index = 0, childCount = children.length, childScope, lastElement = reference, - collection = this.$tryEval(rhs, reference), is_array = isArray(collection); - for ( var key in collection) { + var index = 0, + childCount = children.length, + lastElement = reference, + collection = this.$tryEval(rhs, reference), + is_array = isArray(collection), + collectionLength = 0, + childScope, + key; + + if (is_array) { + collectionLength = collection.length; + } else { + for (key in collection) + if (collection.hasOwnProperty(key)) + collectionLength++; + } + + for (key in collection) { if (!is_array || collection.hasOwnProperty(key)) { if (index < childCount) { // reuse existing child @@ -493,6 +512,9 @@ angularWidget("@ng:repeat", function(expression, element){ if (keyIdent) childScope[keyIdent] = key; lastElement.after(childScope.$element); childScope.$index = index; + childScope.$position = index == 0 ? + 'first' : + (index == collectionLength - 1 ? 'last' : 'middle'); childScope.$element.attr('ng:repeat-index', index); childScope.$init(); children.push(childScope); diff --git a/test/directivesSpec.js b/test/directivesSpec.js index a3aa2481..d575c062 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -135,39 +135,76 @@ describe("directives", function(){ expect(element.text()).toEqual(''); }); - it('should ng:repeat over array', function(){ - var scope = compile(''); - Array.prototype.extraProperty = "should be ignored"; - scope.items = ['misko', 'shyam']; - scope.$eval(); - expect(element.text()).toEqual('misko;shyam;'); - delete Array.prototype.extraProperty; + describe('ng:repeat', function() { - scope.items = ['adam', 'kai', 'brad']; - scope.$eval(); - expect(element.text()).toEqual('adam;kai;brad;'); + it('should ng:repeat over array', function(){ + var scope = compile(''); - scope.items = ['brad']; - scope.$eval(); - expect(element.text()).toEqual('brad;'); - }); + Array.prototype.extraProperty = "should be ignored"; + scope.items = ['misko', 'shyam']; + scope.$eval(); + expect(element.text()).toEqual('misko;shyam;'); + delete Array.prototype.extraProperty; - it('should ng:repeat over object', function(){ - var scope = compile(''); - scope.$set('items', {misko:'swe', shyam:'set'}); - scope.$eval(); - expect(element.text()).toEqual('misko:swe;shyam:set;'); - }); + scope.items = ['adam', 'kai', 'brad']; + scope.$eval(); + expect(element.text()).toEqual('adam;kai;brad;'); + + scope.items = ['brad']; + scope.$eval(); + expect(element.text()).toEqual('brad;'); + }); + + it('should ng:repeat over object', function(){ + var scope = compile(''); + scope.$set('items', {misko:'swe', shyam:'set'}); + scope.$eval(); + expect(element.text()).toEqual('misko:swe;shyam:set;'); + }); - it('should error on wrong parsing of ng:repeat', function(){ - var scope = compile(''); - var log = ""; - log += element.attr('ng-exception') + ';'; - log += element.hasClass('ng-exception') + ';'; - expect(log).toEqual("\"Expected ng:repeat in form of 'item in collection' but got 'i dont parse'.\";true;"); + it('should error on wrong parsing of ng:repeat', function(){ + var scope = compile(''); + var log = ""; + log += element.attr('ng-exception') + ';'; + log += element.hasClass('ng-exception') + ';'; + expect(log).toEqual("\"Expected ng:repeat in form of 'item in collection' but got 'i dont parse'.\";true;"); + }); + + it('should expose iterator offset as $index when iterating over arrays', function() { + var scope = compile(''); + scope.items = ['misko', 'shyam', 'frodo']; + scope.$eval(); + expect(element.text()).toEqual('misko0|shyam1|frodo2|'); + }); + + it('should expose iterator offset as $index when iterating over objects', function() { + var scope = compile(''); + scope.items = {'misko':'m', 'shyam':'s', 'frodo':'f'}; + scope.$eval(); + expect(element.text()).toEqual('misko:m0|shyam:s1|frodo:f2|'); + }); + + it('should expose iterator position as $position when iterating over arrays', function() { + var scope = compile(''); + scope.items = ['misko', 'shyam', 'doug', 'frodo']; + scope.$eval(); + expect(element.text()).toEqual('misko:first|shyam:middle|doug:middle|frodo:last|'); + }); + + it('should expose iterator position as $position when iterating over objects', function() { + var scope = compile(''); + scope.items = {'misko':'m', 'shyam':'s', 'doug':'d', 'frodo':'f'}; + scope.$eval(); + expect(element.text()).toEqual('misko:m:first|shyam:s:middle|doug:d:middle|frodo:f:last|'); + }); }); + it('should ng:watch', function(){ var scope = compile('
'); scope.$eval(); -- cgit v1.2.3