// Returns `true` if the model is in the collection.
return this.get(obj) != null;
// Get the model at the given index.
if (index < 0) index += this.length;
return this.models[index];
// Return models with matching attributes. Useful for simple cases of
where: function(attrs, first) {
return this[first ? 'find' : 'filter'](attrs);
// Return the first model with matching attributes. Useful for simple cases
findWhere: function(attrs) {
return this.where(attrs, true);
// Force the collection to re-sort itself. You don't need to call this under
// normal circumstances, as the set will maintain sort order as each item
sort: function(options) {
var comparator = this.comparator;
if (!comparator) throw new Error('Cannot sort a set without a comparator');
options || (options = {});
var length = comparator.length;
if (_.isFunction(comparator)) comparator = comparator.bind(this);
// Run sort based on type of `comparator`.
if (length === 1 || _.isString(comparator)) {
this.models = this.sortBy(comparator);
this.models.sort(comparator);
if (!options.silent) this.trigger('sort', this, options);
// Pluck an attribute from each model in the collection.
return this.map(attr + '');
// Fetch the default set of models for this collection, resetting the
// collection when they arrive. If `reset: true` is passed, the response
// data will be passed through the `reset` method instead of `set`.
fetch: function(options) {
options = _.extend({parse: true}, options);
var success = options.success;
options.success = function(resp) {
var method = options.reset ? 'reset' : 'set';
collection[method](resp, options);
if (success) success.call(options.context, collection, resp, options);
collection.trigger('sync', collection, resp, options);
wrapError(this, options);
return this.sync('read', this, options);
// Create a new instance of a model in this collection. Add the model to the
// collection immediately, unless `wait: true` is passed, in which case we
// wait for the server to agree.
create: function(model, options) {
options = options ? _.clone(options) : {};
model = this._prepareModel(model, options);
if (!model) return false;
if (!wait) this.add(model, options);
var success = options.success;
options.success = function(m, resp, callbackOpts) {
if (wait) collection.add(m, callbackOpts);
if (success) success.call(callbackOpts.context, m, resp, callbackOpts);
model.save(null, options);
// **parse** converts a response into a list of models to be added to the
// collection. The default implementation is just to pass it through.
parse: function(resp, options) {
// Create a new collection with an identical list of models as this one.
return new this.constructor(this.models, {
comparator: this.comparator
// Define how to uniquely identify models in the collection.
modelId: function(attrs) {
return attrs[this.model.prototype.idAttribute || 'id'];
// Get an iterator of all models in this collection.
return new CollectionIterator(this, ITERATOR_VALUES);
// Get an iterator of all model IDs in this collection.
return new CollectionIterator(this, ITERATOR_KEYS);
// Get an iterator of all [ID, model] tuples in this collection.
return new CollectionIterator(this, ITERATOR_KEYSVALUES);
// Private method to reset all internal state. Called when the collection
// is first initialized or reset.
// Prepare a hash of attributes (or other model) to be added to this
_prepareModel: function(attrs, options) {
if (this._isModel(attrs)) {
if (!attrs.collection) attrs.collection = this;
options = options ? _.clone(options) : {};
options.collection = this;
var model = new this.model(attrs, options);
if (!model.validationError) return model;
this.trigger('invalid', this, model.validationError, options);
// Internal method called by both remove and set.
_removeModels: function(models, options) {
for (var i = 0; i < models.length; i++) {
var model = this.get(models[i]);
var index = this.indexOf(model);
this.models.splice(index, 1);
// Remove references before triggering 'remove' event to prevent an
delete this._byId[model.cid];
var id = this.modelId(model.attributes);
if (id != null) delete this._byId[id];
model.trigger('remove', model, this, options);
this._removeReference(model, options);
// Method for checking whether an object should be considered a model for
// the purposes of adding to the collection.
_isModel: function(model) {
return model instanceof Model;
// Internal method to create a model's ties to a collection.
_addReference: function(model, options) {
this._byId[model.cid] = model;
var id = this.modelId(model.attributes);
if (id != null) this._byId[id] = model;
model.on('all', this._onModelEvent, this);
// Internal method to sever a model's ties to a collection.
_removeReference: function(model, options) {
delete this._byId[model.cid];
var id = this.modelId(model.attributes);
if (id != null) delete this._byId[id];
if (this === model.collection) delete model.collection;
model.off('all', this._onModelEvent, this);
// Internal method called every time a model in the set fires an event.
// Sets need to update their indexes when models change ids. All other
// events simply proxy through. "add" and "remove" events that originate
// in other collections are ignored.
_onModelEvent: function(event, model, collection, options) {
if ((event === 'add' || event === 'remove') && collection !== this) return;
if (event === 'destroy') this.remove(model, options);
if (event === 'change') {
var prevId = this.modelId(model.previousAttributes());
var id = this.modelId(model.attributes);
if (prevId != null) delete this._byId[prevId];
if (id != null) this._byId[id] = model;
this.trigger.apply(this, arguments);
// Defining an @@iterator method implements JavaScript's Iterable protocol.
// In modern ES2015 browsers, this value is found at Symbol.iterator.
var $$iterator = typeof Symbol === 'function' && Symbol.iterator;
Collection.prototype[$$iterator] = Collection.prototype.values;
// A CollectionIterator implements JavaScript's Iterator protocol, allowing the
// use of `for of` loops in modern browsers and interoperation between
// Backbone.Collection and other JavaScript functions and third-party libraries
// which can operate on Iterables.
var CollectionIterator = function(collection, kind) {
this._collection = collection;
// This "enum" defines the three possible kinds of values which can be emitted
// by a CollectionIterator that correspond to the values(), keys() and entries()
// methods on Collection, respectively.
var ITERATOR_KEYSVALUES = 3;
// All Iterators should themselves be Iterable.
CollectionIterator.prototype[$$iterator] = function() {
CollectionIterator.prototype.next = function() {
// Only continue iterating if the iterated collection is long enough.
if (this._index < this._collection.length) {
var model = this._collection.at(this._index);
// Construct a value depending on what kind of values should be iterated.
if (this._kind === ITERATOR_VALUES) {
var id = this._collection.modelId(model.attributes);
if (this._kind === ITERATOR_KEYS) {
} else { // ITERATOR_KEYSVALUES
return {value: value, done: false};
// Once exhausted, remove the reference to the collection so future
// calls to the next method always return done.
this._collection = void 0;
return {value: void 0, done: true};
// Backbone Views are almost more convention than they are actual code. A View
// is simply a JavaScript object that represents a logical chunk of UI in the
// DOM. This might be a single item, an entire list, a sidebar or panel, or
// even the surrounding frame which wraps your whole app. Defining a chunk of
// UI as a **View** allows you to define your DOM events declaratively, without
// having to worry about render order ... and makes it easy for the view to
// react to specific changes in the state of your models.
// Creating a Backbone.View creates its initial element outside of the DOM,
// if an existing element is not provided...
var View = Backbone.View = function(options) {
this.cid = _.uniqueId('view');
this.preinitialize.apply(this, arguments);
_.extend(this, _.pick(options, viewOptions));
this.initialize.apply(this, arguments);
// Cached regex to split keys for `delegate`.
var delegateEventSplitter = /^(\S+)\s*(.*)$/;
// List of view options to be set as properties.
var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
// Set up all inheritable **Backbone.View** properties and methods.
_.extend(View.prototype, Events, {
// The default `tagName` of a View's element is `"div"`.
// jQuery delegate for element lookup, scoped to DOM elements within the
// current view. This should be preferred to global lookups where possible.
return this.$el.find(selector);
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the View
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own
initialize: function(){},
// **render** is the core function that your view should override, in order
// to populate its element (`this.el`), with the appropriate HTML. The
// convention is for **render** to always return `this`.
// Remove this view by taking the element out of the DOM, and removing any
// applicable Backbone.Events listeners.
// Remove this view's element from the document and all event listeners
// attached to it. Exposed for subclasses using an alternative DOM
_removeElement: function() {
// Change the view's element (`this.el` property) and re-delegate the
// view's events on the new element.
setElement: function(element) {
this._setElement(element);
// Creates the `this.el` and `this.$el` references for this view using the
// given `el`. `el` can be a CSS selector or an HTML string, a jQuery
// context or an element. Subclasses can override this to utilize an
// alternative DOM manipulation API and are only required to set the
_setElement: function(el) {
this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
// Set callbacks, where `this.events` is a hash of
// *{"event selector": "callback"}*
// 'mousedown .title': 'edit',
// 'click .button': 'save',
// 'click .open': function(e) { ... }
// pairs. Callbacks will be bound to the view, with `this` set properly.
// Uses event delegation for efficiency.
// Omitting the selector binds the event to `this.el`.
delegateEvents: function(events) {
events || (events = _.result(this, 'events'));
if (!events) return this;
for (var key in events) {
var method = events[key];
if (!_.isFunction(method)) method = this[method];
var match = key.match(delegateEventSplitter);
this.delegate(match[1], match[2], method.bind(this));
// Add a single event listener to the view's element (or a child element
// using `selector`). This only works for delegate-able events: not `focus`,
// `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
delegate: function(eventName, selector, listener) {
this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
// Clears all callbacks previously bound to the view by `delegateEvents`.
// You usually don't need to use this, but may wish to if you have multiple
// Backbone views attached to the same DOM element.
undelegateEvents: function() {
if (this.$el) this.$el.off('.delegateEvents' + this.cid);
// A finer-grained `undelegateEvents` for removing a single delegated event.
// `selector` and `listener` are both optional.
undelegate: function(eventName, selector, listener) {
this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);
// Produces a DOM element to be assigned to your view. Exposed for
// subclasses using an alternative DOM manipulation API.
_createElement: function(tagName) {
return document.createElement(tagName);
// Ensure that the View has a DOM element to render into.
// If `this.el` is a string, pass it through `$()`, take the first
// matching element, and re-assign it to `el`. Otherwise, create
// an element from the `id`, `className` and `tagName` properties.
_ensureElement: function() {
var attrs = _.extend({}, _.result(this, 'attributes'));
if (this.id) attrs.id = _.result(this, 'id');
if (this.className) attrs['class'] = _.result(this, 'className');
this.setElement(this._createElement(_.result(this, 'tagName')));
this._setAttributes(attrs);
this.setElement(_.result(this, 'el'));
// Set attributes from a hash on this view's element. Exposed for
// subclasses using an alternative DOM manipulation API.
_setAttributes: function(attributes) {
this.$el.attr(attributes);
// Proxy Backbone class methods to Underscore functions, wrapping the model's
// `attributes` object or collection's `models` array behind the scenes.
// collection.filter(function(model) { return model.get('age') > 10 });
// collection.each(this.addView);
// `Function#apply` can be slow so we use the method's arg count, if we know it.
var addMethod = function(base, length, method, attribute) {
case 1: return function() {
return base[method](this[attribute]);
case 2: return function(value) {
return base[method](this[attribute], value);
case 3: return function(iteratee, context) {
return base[method](this[attribute], cb(iteratee, this), context);
case 4: return function(iteratee, defaultVal, context) {
return base[method](this[attribute], cb(iteratee, this), defaultVal, context);
default: return function() {
var args = slice.call(arguments);
args.unshift(this[attribute]);
return base[method].apply(base, args);
var addUnderscoreMethods = function(Class, base, methods, attribute) {
_.each(methods, function(length, method) {
if (base[method]) Class.prototype[method] = addMethod(base, length, method, attribute);
// Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
var cb = function(iteratee, instance) {
if (_.isFunction(iteratee)) return iteratee;
if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
var modelMatcher = function(attrs) {
var matcher = _.matches(attrs);
return matcher(model.attributes);
// Underscore methods that we want to implement on the Collection.
// 90% of the core usefulness of Backbone Collections is actually implemented