diff --git a/backbone.js b/backbone.js index d8361d722..721d4b24c 100644 --- a/backbone.js +++ b/backbone.js @@ -688,7 +688,7 @@ if (options.parse) models = this.parse(models, options); var singular = !_.isArray(models); models = singular ? (models ? [models] : []) : models.slice(); - var id, model, attrs, existing, sort; + var id, model, attrs, existing, sort, simpleSort; var at = options.at; var sortable = this.comparator && (at == null) && options.sort !== false; var sortAttr = _.isString(this.comparator) ? this.comparator : null; @@ -739,16 +739,17 @@ // See if sorting is needed, update `length` and splice in new models. if (toAdd.length || (order && order.length)) { - if (sortable) sort = true; this.length += toAdd.length; - if (at != null) { - for (var i = 0, length = toAdd.length; i < length; i++) { - this.models.splice(at + i, 0, toAdd[i]); - } - } else { - if (order) this.models.length = 0; - var orderedModels = order || toAdd; - for (var i = 0, length = orderedModels.length; i < length; i++) { + if (order) this.models.length = 0; + simpleSort = !sort && sortable && (this.comparator.length === 1 || _.isString(this.comparator)); + sort = sort || (!simpleSort && sortable); + var orderedModels = order || toAdd; + for (var i = 0, length = orderedModels.length; i < length; i++) { + if (simpleSort) { + this.models.splice(_.sortedIndex(this.models, orderedModels[i], this.comparator, this), 0, orderedModels[i]); + } else if (at != null) { + this.models.splice(at + i, 0, orderedModels[i]); + } else { this.models.push(orderedModels[i]); } } @@ -762,7 +763,7 @@ for (var i = 0, length = toAdd.length; i < length; i++) { (model = toAdd[i]).trigger('add', model, this, options); } - if (sort || (order && order.length)) this.trigger('sort', this, options); + if (sort || simpleSort || (order && order.length)) this.trigger('sort', this, options); } // Return the added (or merged) model (or models). diff --git a/test/collection.js b/test/collection.js index e1645a998..62b6cead7 100644 --- a/test/collection.js +++ b/test/collection.js @@ -877,6 +877,28 @@ var c = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], { comparator: 'id' }); + c.sort = function(){ throw 'called sort with a value that can be run with _.sortIndex'; }; + c.add([]); + c.add({id: 1}); + c.add([{id: 2}, {id: 3}]); + c.add({id: 4}); + + c = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], { + comparator: function(model) { + return model.id; + } + }); + c.sort = function(){ throw 'called sort with a value that can be run with _.sortIndex'; }; + c.add([]); + c.add({id: 1}); + c.add([{id: 2}, {id: 3}]); + c.add({id: 4}); + + c = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], { + comparator: function(model1, model2) { + return model1.id - model2.id; + } + }); c.sort = function(){ ok(true); }; c.add([]); c.add({id: 1});