Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

ng-repeat : Fix issues when iterating over primitives #1661

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions angularFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ angularFiles = {
'src/ng/httpBackend.js',
'src/ng/locale.js',
'src/ng/timeout.js',
'src/ng/whatChanged.js',

'src/ng/filter.js',
'src/ng/filter/filter.js',
Expand Down
1 change: 1 addition & 0 deletions src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ function publishExternalAPI(angular){
$sniffer: $SnifferProvider,
$templateCache: $TemplateCacheProvider,
$timeout: $TimeoutProvider,
$whatChanged: $WhatChangedProvider,
$window: $WindowProvider
});
}
Expand Down
183 changes: 183 additions & 0 deletions src/apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,186 @@ HashQueueMap.prototype = {
}
}
};

/**
* A generic collection that wraps an array
* @returns an object that wraps an array as a generic collection
*/
var WrappedArray = function(array) {
this.collection = array;
}
WrappedArray.prototype = {
get: function(index) {
return this.collection[index];
},
key: function(index) {
return index;
},
length: function() {
return this.collection.length;
},
copy: function() {
return new WrappedArray(this.collection.slice(0));
}
};

/**
* A generic collection that wraps an object so that you can access its keyed values in order
* @returns an object that wraps an object as a generic collection
*/
var WrappedObject = function(object) {
this.collection = object;
this.keys = [];
for(var key in this.collection) {
if (this.collection.hasOwnProperty(key) && key.charAt(0) != '$') {
this.keys.push(key);
}
}
this.keys.sort();
}
WrappedObject.prototype = {
get: function(index) {
return this.collection[this.keys[index]];
},
key: function(index) {
return this.keys[index];
},
length: function() {
return this.keys.length;
},
copy: function() {
var dst = {};
for(var key in this.collection) {
if (this.collection.hasOwnProperty(key) && key.charAt(0) != '$') {
dst[key] = this.collection[key];
}
}
return new WrappedObject(dst);
}
};

/**
* Track changes to objects (rather than primitives) in between two collections
* @param original {object} collection that has a get method
* @param changed {object} collection that has a get method
*/
function ObjectTracker(original, changed) {
this.original = original;
this.changed = changed;
this.entries = [];
}
ObjectTracker.prototype = {
getEntry: function (obj) {
var key = hashKey(obj);
var entry = this.entries[key];
if ( !angular.isDefined(entry) ) {
entry = ({ newIndexes: [], oldIndexes: [], obj: obj });
}
this.entries[key] = entry;
return entry;
},
// An object is now at this index where it wasn't before
addNewEntry: function(index) {
this.getEntry(this.changed.get(index)).newIndexes.push(index);
},
// An object is no longer at this index
addOldEntry: function(index) {
this.getEntry(this.original.get(index)).oldIndexes.push(index);
}
};

/*
* Track all the changes found between the original and changed collections
* @param original {object} collection that has a get method
* @param changed {object} collection that has a get method
*/
function ChangeTracker(original, changed) {
this.original = original;
this.changed = changed;
// All additions in the form {index, value}
this.additions = [];
// All deletions in the form {index, oldValue}
this.deletions = [];
// All primitive value modifications in the form { index, }
this.modifications = [];
// All moved objects in the form {index, oldIndex, value}
this.moves = [];
}
ChangeTracker.prototype = {
// An addition was found at the given index
pushAddition: function(index) {
this.additions.push({ index: index, value: this.changed.get(index)});
},
// A deletion was found at the given index
pushDeletion: function(index) {
this.deletions.push({ index: index, oldValue: this.original.get(index)});
},
// A modification to a primitive value was found at the given index
pushModification: function(index) {
this.modifications.push( { index: index, oldValue: this.original.get(index), newValue: this.changed.get(index)});
},
// An object has moved from oldIndex to newIndex
pushMove: function(oldIndex, newIndex) {
this.moves.push( { oldIndex: oldIndex, index: newIndex, value: this.original.get(oldIndex)});
}
};

/**
* A flat list of changes ordered by collection key
*/
function FlattenedChanges(changes) {
this.changes = [];
var index, item;
// Flatten all the changes into a array ordered by index
for(index = 0; index < changes.modifications.length; index++) {
item = changes.modifications[index];
this.modified(item);
}
for(index = 0; index < changes.deletions.length; index++) {
item = changes.deletions[index];
this.deleted(item);
}
for(index = 0; index < changes.additions.length; index++) {
item = changes.additions[index];
this.added(item);
}
for(index = 0; index < changes.moves.length; index++) {
item = changes.moves[index];
this.moved(item);
}
}
FlattenedChanges.prototype = {
modified: function(item) {
item.modified = true;
this.changes[item.index] = item;
},
moved: function(change) {
var item = this.changes[change.index];
if ( angular.isDefined(item) ) {
item.value = change.value;
item.oldIndex = change.oldIndex;
} else {
item = change;
}
item.moved = true;
this.changes[change.index] = item;
},
added: function(change){
var item = this.changes[change.index];
if ( angular.isDefined(item) ) {
item.value = change.value;
} else {
item = change;
}
item.added = true;
this.changes[change.index] = item;
},
deleted: function(change) {
var item = this.changes[change.index];
if ( !angular.isDefined(item) ) {
item = change;
}
item.deleted = true;
this.changes[change.index] = item;
}
};
Loading