|
42 | 42 |
|
43 | 43 | // Create a local reference to a common array method we'll want to use later.
|
44 | 44 | var slice = Array.prototype.slice;
|
45 |
| - var splice = function(array, insert, at) { |
46 |
| - var length = insert.length; |
47 |
| - var result = Array(array.length + length); |
48 |
| - for (var i = 0; i < at; i++) result[i] = array[i]; |
49 |
| - for (i = 0; i < length; i++) result[i + at] = insert[i]; |
50 |
| - for (i = at; i < array.length; i++) result[i + length] = array[i]; |
51 |
| - return result; |
52 |
| - }; |
53 | 45 |
|
54 | 46 | // Current version of the library. Keep in sync with `package.json`.
|
55 | 47 | Backbone.VERSION = '1.2.0';
|
|
754 | 746 | var setOptions = {add: true, remove: true, merge: true};
|
755 | 747 | var addOptions = {add: true, remove: false};
|
756 | 748 |
|
| 749 | + // Splices `insert` into `array` at index `at`. |
| 750 | + var splice = function(array, insert, at) { |
| 751 | + var tail = Array(result.length - at); |
| 752 | + var length = insert.length; |
| 753 | + for (var i = 0; i < tail.length; i++) tail[i] = result[i + at]; |
| 754 | + for (i = 0; i < length; i++) result[i + at] = insert[i]; |
| 755 | + for (i = 0; i < tail.length; i++) result[i + length + at] = tail[i]; |
| 756 | + }; |
| 757 | + |
757 | 758 | // Define the Collection's inheritable methods.
|
758 | 759 | _.extend(Collection.prototype, Events, {
|
759 | 760 |
|
|
802 | 803 | if (options.parse && !this._isModel(models)) models = this.parse(models, options);
|
803 | 804 |
|
804 | 805 | var singular = !_.isArray(models);
|
805 |
| - models = singular ? [models] : models; |
| 806 | + models = singular ? [models] : _.clone(models); |
806 | 807 |
|
807 | 808 | var at = options.at;
|
808 | 809 | if (at != null) at = +at;
|
|
841 | 842 | modelMap[existing.cid] = true;
|
842 | 843 | set.push(existing);
|
843 | 844 | }
|
| 845 | + models[i] = existing; |
844 | 846 |
|
845 | 847 | // If this is a new, valid model, push it to the `toAdd` list.
|
846 | 848 | } else if (add) {
|
847 |
| - model = this._prepareModel(model, options); |
| 849 | + model = models[i] = this._prepareModel(model, options); |
848 | 850 | if (model) {
|
849 | 851 | toAdd.push(model);
|
850 | 852 | this._addReference(model, options);
|
|
865 | 867 |
|
866 | 868 | // See if sorting is needed, update `length` and splice in new models.
|
867 | 869 | var orderChanged = false;
|
868 |
| - if (set.length && !sortable && add && remove) { |
869 |
| - orderChanged = set.length != this.length || _.any(this.models, function(model, index) { |
| 870 | + var replace = !sortable && add && remove; |
| 871 | + if (set.length && replace) { |
| 872 | + orderChanged = this.length != set.length || _.any(this.models, function(model, index) { |
870 | 873 | return model !== set[index];
|
871 | 874 | });
|
872 |
| - this.models = set.slice(); |
873 |
| - this.length = set.length; |
| 875 | + this.models.length = 0; |
| 876 | + splice(this.models, set, 0); |
| 877 | + this.length = this.models.length; |
874 | 878 | } else if (toAdd.length) {
|
875 | 879 | if (sortable) sort = true;
|
876 |
| - this.models = splice(this.models, toAdd, at == null ? this.length : at); |
877 |
| - this.length += toAdd.length; |
| 880 | + splice(this.models, toAdd, at == null ? this.length : at); |
| 881 | + this.length = this.models.length; |
878 | 882 | }
|
879 | 883 |
|
880 | 884 | // Silently sort the collection if appropriate.
|
|
892 | 896 | }
|
893 | 897 |
|
894 | 898 | // Return the added (or merged) model (or models).
|
895 |
| - return singular ? set[0] : set; |
| 899 | + return singular ? models[0] : models; |
896 | 900 | },
|
897 | 901 |
|
898 | 902 | // When you have more items than you want to add or remove individually,
|
|
0 commit comments