diff options
Diffstat (limited to 'src/widgets.js')
| -rw-r--r-- | src/widgets.js | 98 |
1 files changed, 55 insertions, 43 deletions
diff --git a/src/widgets.js b/src/widgets.js index c70e9efa..11d9a2f0 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -361,7 +361,7 @@ angularWidget('@ng:repeat', function(expression, element){ // We expect this to be a rare case. var lastOrder = new HashQueueMap(); this.$watch(function(scope){ - var index = 0, + var index, length, collection = scope.$eval(rhs), collectionLength = size(collection, true), childScope, @@ -372,52 +372,64 @@ angularWidget('@ng:repeat', function(expression, element){ array, last, // last object information {scope, element, index} cursor = iterStartElement; // current position of the node - for (key in collection) { - if (collection.hasOwnProperty(key) && key.charAt(0) != '$') { - last = lastOrder.shift(value = collection[key]); - if (last) { - // if we have already seen this object, then we need to reuse the - // associated scope/element - childScope = last.scope; - nextOrder.push(value, last); - - if (index === last.index) { - // do nothing - cursor = last.element; - } else { - // existing item which got moved - last.index = index; - // This may be a noop, if the element is next, but I don't know of a good way to - // figure this out, since it would require extra DOM access, so let's just hope that - // the browsers realizes that it is noop, and treats it as such. - cursor.after(last.element); - cursor = last.element; - } - } else { - // new item which we don't know about - childScope = parentScope.$new(); + if (!isArray(collection)) { + // if object, extract keys, sort them and use to determine order of iteration over obj props + array = []; + for(key in collection) { + if (collection.hasOwnProperty(key) && key.charAt(0) != '$') { + array.push(key); } + } + array.sort(); + } else { + array = collection || []; + } - childScope[valueIdent] = collection[key]; - if (keyIdent) childScope[keyIdent] = key; - childScope.$index = index; - childScope.$position = index == 0 - ? 'first' - : (index == collectionLength - 1 ? 'last' : 'middle'); - - if (!last) { - linker(childScope, function(clone){ - cursor.after(clone); - last = { - scope: childScope, - element: (cursor = clone), - index: index - }; - nextOrder.push(value, last); - }); + // we are not using forEach for perf reasons (trying to avoid #call) + for (index = 0, length = array.length; index < length; index++) { + key = (collection === array) ? index : array[index]; + value = collection[key]; + last = lastOrder.shift(value); + if (last) { + // if we have already seen this object, then we need to reuse the + // associated scope/element + childScope = last.scope; + nextOrder.push(value, last); + + if (index === last.index) { + // do nothing + cursor = last.element; + } else { + // existing item which got moved + last.index = index; + // This may be a noop, if the element is next, but I don't know of a good way to + // figure this out, since it would require extra DOM access, so let's just hope that + // the browsers realizes that it is noop, and treats it as such. + cursor.after(last.element); + cursor = last.element; } + } else { + // new item which we don't know about + childScope = parentScope.$new(); + } - index ++; + childScope[valueIdent] = value; + if (keyIdent) childScope[keyIdent] = key; + childScope.$index = index; + childScope.$position = index == 0 + ? 'first' + : (index == collectionLength - 1 ? 'last' : 'middle'); + + if (!last) { + linker(childScope, function(clone){ + cursor.after(clone); + last = { + scope: childScope, + element: (cursor = clone), + index: index + }; + nextOrder.push(value, last); + }); } } |
