Update vendors.

Former-commit-id: 6ab66f9ea6fd881e8c5ed18e84b9a24656496e10
This commit is contained in:
John-David Dalton
2013-02-17 16:38:23 -08:00
parent 25e4231d7b
commit 8183740c04
6 changed files with 129 additions and 237 deletions

View File

@@ -19,7 +19,7 @@
var closureId = '23cf67d0f0b979d97631fc108a2a43bb82225994'; var closureId = '23cf67d0f0b979d97631fc108a2a43bb82225994';
/** The Git object ID of `uglifyjs.tar.gz` */ /** The Git object ID of `uglifyjs.tar.gz` */
var uglifyId = '326ede8f4a3d8e0ae82cec7b9579d45892836629'; var uglifyId = 'a934fb18f8fa2768c6a68de44b6e035fe96a268b';
/** The path of the directory that is the base of the repository */ /** The path of the directory that is the base of the repository */
var basePath = fs.realpathSync(path.join(__dirname, '..')); var basePath = fs.realpathSync(path.join(__dirname, '..'));

View File

@@ -1,4 +1,4 @@
Copyright (c) 2010-2013 Jeremy Ashkenas, DocumentCloud Copyright (c) 2010-2012 Jeremy Ashkenas, DocumentCloud
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation

View File

@@ -1,6 +1,6 @@
// Backbone.js 0.9.10 // Backbone.js 0.9.10
// (c) 2010-2013 Jeremy Ashkenas, DocumentCloud Inc. // (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Backbone may be freely distributed under the MIT license. // Backbone may be freely distributed under the MIT license.
// For all details and documentation: // For all details and documentation:
// http://backbonejs.org // http://backbonejs.org
@@ -89,15 +89,15 @@
// Optimized internal dispatch function for triggering events. Tries to // Optimized internal dispatch function for triggering events. Tries to
// keep the usual cases speedy (most Backbone events have 3 arguments). // keep the usual cases speedy (most Backbone events have 3 arguments).
var triggerEvents = function(events, args) { var triggerEvents = function(events, args) {
var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; var ev, i = -1, l = events.length;
switch (args.length) { switch (args.length) {
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
return; return;
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
return; return;
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
return; return;
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
return; return;
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
} }
@@ -119,24 +119,25 @@
// to a `callback` function. Passing `"all"` will bind the callback to // to a `callback` function. Passing `"all"` will bind the callback to
// all events fired. // all events fired.
on: function(name, callback, context) { on: function(name, callback, context) {
if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; if (!(eventsApi(this, 'on', name, [callback, context]) && callback)) return this;
this._events || (this._events = {}); this._events || (this._events = {});
var events = this._events[name] || (this._events[name] = []); var list = this._events[name] || (this._events[name] = []);
events.push({callback: callback, context: context, ctx: context || this}); list.push({callback: callback, context: context, ctx: context || this});
return this; return this;
}, },
// Bind events to only be triggered a single time. After the first time // Bind events to only be triggered a single time. After the first time
// the callback is invoked, it will be removed. // the callback is invoked, it will be removed.
once: function(name, callback, context) { once: function(name, callback, context) {
if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; if (!(eventsApi(this, 'once', name, [callback, context]) && callback)) return this;
var self = this; var self = this;
var once = _.once(function() { var once = _.once(function() {
self.off(name, once); self.off(name, once);
callback.apply(this, arguments); callback.apply(this, arguments);
}); });
once._callback = callback; once._callback = callback;
return this.on(name, once, context); this.on(name, once, context);
return this;
}, },
// Remove one or many callbacks. If `context` is null, removes all // Remove one or many callbacks. If `context` is null, removes all
@@ -144,7 +145,7 @@
// callbacks for the event. If `name` is null, removes all bound // callbacks for the event. If `name` is null, removes all bound
// callbacks for all events. // callbacks for all events.
off: function(name, callback, context) { off: function(name, callback, context) {
var retain, ev, events, names, i, l, j, k; var list, ev, events, names, i, l, j, k;
if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
if (!name && !callback && !context) { if (!name && !callback && !context) {
this._events = {}; this._events = {};
@@ -154,19 +155,19 @@
names = name ? [name] : _.keys(this._events); names = name ? [name] : _.keys(this._events);
for (i = 0, l = names.length; i < l; i++) { for (i = 0, l = names.length; i < l; i++) {
name = names[i]; name = names[i];
if (events = this._events[name]) { if (list = this._events[name]) {
this._events[name] = retain = []; events = [];
if (callback || context) { if (callback || context) {
for (j = 0, k = events.length; j < k; j++) { for (j = 0, k = list.length; j < k; j++) {
ev = events[j]; ev = list[j];
if ((callback && callback !== ev.callback && if ((callback && callback !== ev.callback &&
callback !== ev.callback._callback) || callback !== ev.callback._callback) ||
(context && context !== ev.context)) { (context && context !== ev.context)) {
retain.push(ev); events.push(ev);
} }
} }
} }
if (!retain.length) delete this._events[name]; this._events[name] = events;
} }
} }
@@ -188,37 +189,35 @@
return this; return this;
}, },
// An inversion-of-control version of `on`. Tell *this* object to listen to
// an event in another object ... keeping track of what it's listening to.
listenTo: function(obj, name, callback) {
var listeners = this._listeners || (this._listeners = {});
var id = obj._listenerId || (obj._listenerId = _.uniqueId('l'));
listeners[id] = obj;
obj.on(name, typeof name === 'object' ? this : callback, this);
return this;
},
// Tell this object to stop listening to either specific events ... or // Tell this object to stop listening to either specific events ... or
// to every object it's currently listening to. // to every object it's currently listening to.
stopListening: function(obj, name, callback) { stopListening: function(obj, name, callback) {
var listeners = this._listeners; var listeners = this._listeners;
if (!listeners) return this; if (!listeners) return;
var deleteListener = !name && !callback; if (obj) {
if (typeof name === 'object') callback = this; obj.off(name, typeof name === 'object' ? this : callback, this);
if (obj) (listeners = {})[obj._listenerId] = obj; if (!name && !callback) delete listeners[obj._listenerId];
for (var id in listeners) { } else {
listeners[id].off(name, callback, this); if (typeof name === 'object') callback = this;
if (deleteListener) delete this._listeners[id]; for (var id in listeners) {
listeners[id].off(name, callback, this);
}
this._listeners = {};
} }
return this; return this;
} }
}; };
var listenMethods = {listenTo: 'on', listenToOnce: 'once'};
// An inversion-of-control versions of `on` and `once`. Tell *this* object to listen to
// an event in another object ... keeping track of what it's listening to.
_.each(listenMethods, function(implementation, method) {
Events[method] = function(obj, name, callback) {
var listeners = this._listeners || (this._listeners = {});
var id = obj._listenerId || (obj._listenerId = _.uniqueId('l'));
listeners[id] = obj;
if (typeof name === 'object') callback = this;
obj[implementation](name, callback, this);
return this;
};
});
// Aliases for backwards compatibility. // Aliases for backwards compatibility.
Events.bind = Events.on; Events.bind = Events.on;
Events.unbind = Events.off; Events.unbind = Events.off;
@@ -253,9 +252,6 @@
// A hash of attributes whose current and previous value differ. // A hash of attributes whose current and previous value differ.
changed: null, changed: null,
// The value returned during the last failed validation.
validationError: null,
// The default name for the JSON `id` attribute is `"id"`. MongoDB and // The default name for the JSON `id` attribute is `"id"`. MongoDB and
// CouchDB users may want to set this to `"_id"`. // CouchDB users may want to set this to `"_id"`.
idAttribute: 'id', idAttribute: 'id',
@@ -418,14 +414,11 @@
fetch: function(options) { fetch: function(options) {
options = options ? _.clone(options) : {}; options = options ? _.clone(options) : {};
if (options.parse === void 0) options.parse = true; if (options.parse === void 0) options.parse = true;
var model = this;
var success = options.success; var success = options.success;
options.success = function(resp) { options.success = function(model, resp, options) {
if (!model.set(model.parse(resp, options), options)) return false; if (!model.set(model.parse(resp, options), options)) return false;
if (success) success(model, resp, options); if (success) success(model, resp, options);
model.trigger('sync', model, resp, options);
}; };
wrapError(this, options);
return this.sync('read', this, options); return this.sync('read', this, options);
}, },
@@ -433,7 +426,7 @@
// If the server returns an attributes hash that differs, the model's // If the server returns an attributes hash that differs, the model's
// state will be `set` again. // state will be `set` again.
save: function(key, val, options) { save: function(key, val, options) {
var attrs, method, xhr, attributes = this.attributes; var attrs, success, method, xhr, attributes = this.attributes;
// Handle both `"key", value` and `{key: value}` -style arguments. // Handle both `"key", value` and `{key: value}` -style arguments.
if (key == null || typeof key === 'object') { if (key == null || typeof key === 'object') {
@@ -459,9 +452,8 @@
// After a successful server-side save, the client is (optionally) // After a successful server-side save, the client is (optionally)
// updated with the server-side state. // updated with the server-side state.
if (options.parse === void 0) options.parse = true; if (options.parse === void 0) options.parse = true;
var model = this; success = options.success;
var success = options.success; options.success = function(model, resp, options) {
options.success = function(resp) {
// Ensure attributes are restored during synchronous saves. // Ensure attributes are restored during synchronous saves.
model.attributes = attributes; model.attributes = attributes;
var serverAttrs = model.parse(resp, options); var serverAttrs = model.parse(resp, options);
@@ -470,10 +462,9 @@
return false; return false;
} }
if (success) success(model, resp, options); if (success) success(model, resp, options);
model.trigger('sync', model, resp, options);
}; };
wrapError(this, options);
// Finish configuring and sending the Ajax request.
method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
if (method === 'patch') options.attrs = attrs; if (method === 'patch') options.attrs = attrs;
xhr = this.sync(method, this, options); xhr = this.sync(method, this, options);
@@ -496,17 +487,15 @@
model.trigger('destroy', model, model.collection, options); model.trigger('destroy', model, model.collection, options);
}; };
options.success = function(resp) { options.success = function(model, resp, options) {
if (options.wait || model.isNew()) destroy(); if (options.wait || model.isNew()) destroy();
if (success) success(model, resp, options); if (success) success(model, resp, options);
if (!model.isNew()) model.trigger('sync', model, resp, options);
}; };
if (this.isNew()) { if (this.isNew()) {
options.success(); options.success(this, null, options);
return false; return false;
} }
wrapError(this, options);
var xhr = this.sync('delete', this, options); var xhr = this.sync('delete', this, options);
if (!options.wait) destroy(); if (!options.wait) destroy();
@@ -544,8 +533,8 @@
}, },
// Run validation against the next complete set of model attributes, // Run validation against the next complete set of model attributes,
// returning `true` if all is well. Otherwise, fire an // returning `true` if all is well. Otherwise, fire a general
// `"invalid"` event and call the invalid callback, if specified. // `"error"` event and call the error callback, if specified.
_validate: function(attrs, options) { _validate: function(attrs, options) {
if (!options.validate || !this.validate) return true; if (!options.validate || !this.validate) return true;
attrs = _.extend({}, this.attributes, attrs); attrs = _.extend({}, this.attributes, attrs);
@@ -567,6 +556,7 @@
options || (options = {}); options || (options = {});
if (options.model) this.model = options.model; if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator; if (options.comparator !== void 0) this.comparator = options.comparator;
this.models = [];
this._reset(); this._reset();
this.initialize.apply(this, arguments); this.initialize.apply(this, arguments);
if (models) this.reset(models, _.extend({silent: true}, options)); if (models) this.reset(models, _.extend({silent: true}, options));
@@ -601,13 +591,16 @@
var i, l, model, attrs, existing, doSort, add, at, sort, sortAttr; var i, l, model, attrs, existing, doSort, add, at, sort, sortAttr;
add = []; add = [];
at = options.at; at = options.at;
sort = this.comparator && (at == null) && options.sort !== false; sort = this.comparator && (at == null) && options.sort != false;
sortAttr = _.isString(this.comparator) ? this.comparator : null; sortAttr = _.isString(this.comparator) ? this.comparator : null;
// Turn bare objects into model references, and prevent invalid models // Turn bare objects into model references, and prevent invalid models
// from being added. // from being added.
for (i = 0, l = models.length; i < l; i++) { for (i = 0, l = models.length; i < l; i++) {
if (!(model = this._prepareModel(attrs = models[i], options))) continue; if (!(model = this._prepareModel(attrs = models[i], options))) {
this.trigger('invalid', this, attrs, options);
continue;
}
// If a duplicate is found, prevent it from being added and // If a duplicate is found, prevent it from being added and
// optionally merge it into the existing model. // optionally merge it into the existing model.
@@ -714,7 +707,8 @@
// Get a model from the set by id. // Get a model from the set by id.
get: function(obj) { get: function(obj) {
if (obj == null) return void 0; if (obj == null) return void 0;
return this._byId[obj.id || obj.cid || obj]; this._idAttr || (this._idAttr = this.model.prototype.idAttribute);
return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj];
}, },
// Get the model at the given index. // Get the model at the given index.
@@ -722,11 +716,10 @@
return this.models[index]; return this.models[index];
}, },
// Return models with matching attributes. Useful for simple cases of // Return models with matching attributes. Useful for simple cases of `filter`.
// `filter`. where: function(attrs) {
where: function(attrs, first) { if (_.isEmpty(attrs)) return [];
if (_.isEmpty(attrs)) return first ? void 0 : []; return this.filter(function(model) {
return this[first ? 'find' : 'filter'](function(model) {
for (var key in attrs) { for (var key in attrs) {
if (attrs[key] !== model.get(key)) return false; if (attrs[key] !== model.get(key)) return false;
} }
@@ -734,12 +727,6 @@
}); });
}, },
// Return the first model with matching attributes. Useful for simple cases
// of `find`.
findWhere: function(attrs) {
return this.where(attrs, true);
},
// Force the collection to re-sort itself. You don't need to call this under // 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 // normal circumstances, as the set will maintain sort order as each item
// is added. // is added.
@@ -770,7 +757,7 @@
update: function(models, options) { update: function(models, options) {
options = _.extend({add: true, merge: true, remove: true}, options); options = _.extend({add: true, merge: true, remove: true}, options);
if (options.parse) models = this.parse(models, options); if (options.parse) models = this.parse(models, options);
var attrs, model, i, l, existing; var model, i, l, existing;
var add = [], remove = [], modelMap = {}; var add = [], remove = [], modelMap = {};
// Allow a single model (or no argument) to be passed. // Allow a single model (or no argument) to be passed.
@@ -781,12 +768,11 @@
// Determine which models to add and merge, and which to remove. // Determine which models to add and merge, and which to remove.
for (i = 0, l = models.length; i < l; i++) { for (i = 0, l = models.length; i < l; i++) {
if (!((attrs = models[i]) instanceof Model)) attrs = _.clone(attrs); model = models[i];
if (!(model = this._prepareModel(attrs, options))) continue;
existing = this.get(model); existing = this.get(model);
if (options.remove && existing) modelMap[existing.cid] = true; if (options.remove && existing) modelMap[existing.cid] = true;
if ((options.add && !existing) || (options.merge && existing)) { if ((options.add && !existing) || (options.merge && existing)) {
add.push(models[i]); add.push(model);
} }
} }
if (options.remove) { if (options.remove) {
@@ -811,7 +797,7 @@
for (var i = 0, l = this.models.length; i < l; i++) { for (var i = 0, l = this.models.length; i < l; i++) {
this._removeReference(this.models[i]); this._removeReference(this.models[i]);
} }
options.previousModels = this.models; options.previousModels = this.models.slice();
this._reset(); this._reset();
if (models) this.add(models, _.extend({silent: true}, options)); if (models) this.add(models, _.extend({silent: true}, options));
if (!options.silent) this.trigger('reset', this, options); if (!options.silent) this.trigger('reset', this, options);
@@ -825,14 +811,11 @@
options = options ? _.clone(options) : {}; options = options ? _.clone(options) : {};
if (options.parse === void 0) options.parse = true; if (options.parse === void 0) options.parse = true;
var success = options.success; var success = options.success;
var collection = this; options.success = function(collection, resp, options) {
options.success = function(resp) {
var method = options.update ? 'update' : 'reset'; var method = options.update ? 'update' : 'reset';
collection[method](resp, options); collection[method](resp, options);
if (success) success(collection, resp, options); if (success) success(collection, resp, options);
collection.trigger('sync', collection, resp, options);
}; };
wrapError(this, options);
return this.sync('read', this, options); return this.sync('read', this, options);
}, },
@@ -845,7 +828,7 @@
if (!options.wait) this.add(model, options); if (!options.wait) this.add(model, options);
var collection = this; var collection = this;
var success = options.success; var success = options.success;
options.success = function(resp) { options.success = function(model, resp, options) {
if (options.wait) collection.add(model, options); if (options.wait) collection.add(model, options);
if (success) success(model, resp, options); if (success) success(model, resp, options);
}; };
@@ -867,7 +850,7 @@
// Reset all internal state. Called when the collection is reset. // Reset all internal state. Called when the collection is reset.
_reset: function() { _reset: function() {
this.length = 0; this.length = 0;
this.models = []; this.models.length = 0;
this._byId = {}; this._byId = {};
}, },
@@ -880,10 +863,7 @@
options || (options = {}); options || (options = {});
options.collection = this; options.collection = this;
var model = new this.model(attrs, options); var model = new this.model(attrs, options);
if (!model._validate(attrs, options)) { if (!model._validate(attrs, options)) return false;
this.trigger('invalid', this, attrs, options);
return false;
}
return model; return model;
}, },
@@ -1320,7 +1300,7 @@
// This only works for delegate-able events: not `focus`, `blur`, and // This only works for delegate-able events: not `focus`, `blur`, and
// not `change`, `submit`, and `reset` in Internet Explorer. // not `change`, `submit`, and `reset` in Internet Explorer.
delegateEvents: function(events) { delegateEvents: function(events) {
if (!(events || (events = _.result(this, 'events')))) return this; if (!(events || (events = _.result(this, 'events')))) return;
this.undelegateEvents(); this.undelegateEvents();
for (var key in events) { for (var key in events) {
var method = events[key]; var method = events[key];
@@ -1336,7 +1316,6 @@
this.$el.on(eventName, selector, method); this.$el.on(eventName, selector, method);
} }
} }
return this;
}, },
// Clears all callbacks previously bound to the view with `delegateEvents`. // Clears all callbacks previously bound to the view with `delegateEvents`.
@@ -1344,7 +1323,6 @@
// Backbone views attached to the same DOM element. // Backbone views attached to the same DOM element.
undelegateEvents: function() { undelegateEvents: function() {
this.$el.off('.delegateEvents' + this.cid); this.$el.off('.delegateEvents' + this.cid);
return this;
}, },
// Performs the initial configuration of a View with a set of options. // Performs the initial configuration of a View with a set of options.
@@ -1447,6 +1425,18 @@
params.processData = false; params.processData = false;
} }
var success = options.success;
options.success = function(resp) {
if (success) success(model, resp, options);
model.trigger('sync', model, resp, options);
};
var error = options.error;
options.error = function(xhr) {
if (error) error(model, xhr, options);
model.trigger('error', model, xhr, options);
};
// Make the request, allowing the user to override any Ajax options. // Make the request, allowing the user to override any Ajax options.
var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
model.trigger('request', model, xhr, options); model.trigger('request', model, xhr, options);
@@ -1505,13 +1495,4 @@
throw new Error('A "url" property or function must be specified'); throw new Error('A "url" property or function must be specified');
}; };
// Wrap an optional error callback with a fallback error event.
var wrapError = function (model, options) {
var error = options.error;
options.error = function(resp) {
if (error) error(model, resp, options);
model.trigger('error', model, resp, options);
};
};
}).call(this); }).call(this);

View File

@@ -70,20 +70,22 @@ $(document).ready(function() {
equal(col.get(col.first().cid), col.first()); equal(col.get(col.first().cid), col.first());
}); });
test("get with non-default ids", 5, function() { test("get with non-default ids", 4, function() {
var col = new Backbone.Collection(); var col = new Backbone.Collection();
var MongoModel = Backbone.Model.extend({idAttribute: '_id'}); var MongoModel = Backbone.Model.extend({
idAttribute: '_id'
});
var model = new MongoModel({_id: 100}); var model = new MongoModel({_id: 100});
col.add(model); col.push(model);
equal(col.get(100), model); equal(col.get(100), model);
equal(col.get(model.cid), model); model.set({_id: 101});
equal(col.get(model), model); equal(col.get(101), model);
equal(col.get(101), void 0);
var col2 = new Backbone.Collection(); var Col2 = Backbone.Collection.extend({ model: MongoModel });
col2.model = MongoModel; var col2 = new Col2();
col2.add(model.attributes); col2.push(model);
equal(col2.get(model.clone()), col2.first()); equal(col2.get({_id: 101}), model);
equal(col2.get(model.clone()), model);
}); });
test("update index when id changes", 3, function() { test("update index when id changes", 3, function() {
@@ -360,7 +362,9 @@ $(document).ready(function() {
test("model destroy removes from all collections", 3, function() { test("model destroy removes from all collections", 3, function() {
var e = new Backbone.Model({id: 5, title: 'Othello'}); var e = new Backbone.Model({id: 5, title: 'Othello'});
e.sync = function(method, model, options) { options.success(); }; e.sync = function(method, model, options) {
options.success(model, [], options);
};
var colE = new Backbone.Collection([e]); var colE = new Backbone.Collection([e]);
var colF = new Backbone.Collection([e]); var colF = new Backbone.Collection([e]);
e.destroy(); e.destroy();
@@ -392,15 +396,6 @@ $(document).ready(function() {
equal(this.syncArgs.options.parse, false); equal(this.syncArgs.options.parse, false);
}); });
test("fetch with an error response triggers an error event", 1, function () {
var collection = new Backbone.Collection();
collection.on('error', function () {
ok(true);
});
collection.sync = function (method, model, options) { options.error(); };
collection.fetch();
});
test("ensure fetch only parses once", 1, function() { test("ensure fetch only parses once", 1, function() {
var collection = new Backbone.Collection; var collection = new Backbone.Collection;
var counter = 0; var counter = 0;
@@ -410,7 +405,7 @@ $(document).ready(function() {
}; };
collection.url = '/test'; collection.url = '/test';
collection.fetch(); collection.fetch();
this.syncArgs.options.success(); this.syncArgs.options.success([]);
equal(counter, 1); equal(counter, 1);
}); });
@@ -466,10 +461,9 @@ $(document).ready(function() {
equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
}); });
test("where and findWhere", 8, function() { test("where", 6, function() {
var model = new Backbone.Model({a: 1});
var coll = new Backbone.Collection([ var coll = new Backbone.Collection([
model, {a: 1},
{a: 1}, {a: 1},
{a: 1, b: 2}, {a: 1, b: 2},
{a: 2, b: 2}, {a: 2, b: 2},
@@ -481,8 +475,6 @@ $(document).ready(function() {
equal(coll.where({b: 1}).length, 0); equal(coll.where({b: 1}).length, 0);
equal(coll.where({b: 2}).length, 2); equal(coll.where({b: 2}).length, 2);
equal(coll.where({a: 1, b: 2}).length, 1); equal(coll.where({a: 1, b: 2}).length, 1);
equal(coll.findWhere({a: 1}), model);
equal(coll.findWhere({a: 4}), void 0);
}); });
test("Underscore methods", 13, function() { test("Underscore methods", 13, function() {
@@ -492,10 +484,10 @@ $(document).ready(function() {
equal(col.indexOf(b), 1); equal(col.indexOf(b), 1);
equal(col.size(), 4); equal(col.size(), 4);
equal(col.rest().length, 3); equal(col.rest().length, 3);
ok(!_.include(col.rest(), a)); ok(!_.include(col.rest()), a);
ok(_.include(col.rest(), d)); ok(!_.include(col.rest()), d);
ok(!col.isEmpty()); ok(!col.isEmpty());
ok(!_.include(col.without(d), d)); ok(!_.include(col.without(d)), d);
equal(col.max(function(model){ return model.id; }).id, 3); equal(col.max(function(model){ return model.id; }).id, 3);
equal(col.min(function(model){ return model.id; }).id, 0); equal(col.min(function(model){ return model.id; }).id, 0);
deepEqual(col.chain() deepEqual(col.chain()
@@ -519,7 +511,7 @@ $(document).ready(function() {
test("reset", 10, function() { test("reset", 10, function() {
var resetCount = 0; var resetCount = 0;
var models = col.models; var models = col.models.slice();
col.on('reset', function() { resetCount += 1; }); col.on('reset', function() { resetCount += 1; });
col.reset([]); col.reset([]);
equal(resetCount, 1); equal(resetCount, 1);
@@ -710,7 +702,9 @@ $(document).ready(function() {
test("#1447 - create with wait adds model.", 1, function() { test("#1447 - create with wait adds model.", 1, function() {
var collection = new Backbone.Collection; var collection = new Backbone.Collection;
var model = new Backbone.Model; var model = new Backbone.Model;
model.sync = function(method, model, options){ options.success(); }; model.sync = function(method, model, options){
options.success(model, [], options);
};
collection.on('add', function(){ ok(true); }); collection.on('add', function(){ ok(true); });
collection.create(model, {wait: true}); collection.create(model, {wait: true});
}); });
@@ -934,35 +928,6 @@ $(document).ready(function() {
equal(col.length, 1); equal(col.length, 1);
}); });
test("`update` and model level `parse`", function() {
var Model = Backbone.Model.extend({
parse: function (res) { return res.model; }
});
var Collection = Backbone.Collection.extend({
model: Model,
parse: function (res) { return res.models; }
});
var model = new Model({id: 1});
var collection = new Collection(model);
collection.update({models: [
{model: {id: 1}},
{model: {id: 2}}
]}, {parse: true});
equal(collection.first(), model);
});
test("`update` data is only parsed once", function() {
var collection = new Backbone.Collection();
collection.model = Backbone.Model.extend({
parse: function (data) {
equal(data.parsed, void 0);
data.parsed = true;
return data;
}
});
collection.update({}, {parse: true});
});
test("#1894 - Push should not trigger a sort", 0, function() { test("#1894 - Push should not trigger a sort", 0, function() {
var Collection = Backbone.Collection.extend({ var Collection = Backbone.Collection.extend({
comparator: 'id', comparator: 'id',

View File

@@ -99,43 +99,6 @@ $(document).ready(function() {
a.listenTo(b, 'event2', cb); a.listenTo(b, 'event2', cb);
a.stopListening(null, {event: cb}); a.stopListening(null, {event: cb});
b.trigger('event event2'); b.trigger('event event2');
b.off();
a.listenTo(b, 'event event2', cb);
a.stopListening(null, 'event');
a.stopListening();
b.trigger('event2');
});
test("listenToOnce and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function() { ok(true); });
b.trigger('anything');
b.trigger('anything');
a.listenToOnce(b, 'all', function() { ok(false); });
a.stopListening();
b.trigger('anything');
});
test("listenTo, listenToOnce and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function() { ok(true); });
b.trigger('anything');
b.trigger('anything');
a.listenTo(b, 'all', function() { ok(false); });
a.stopListening();
b.trigger('anything');
});
test("listenTo and stopListening with event maps", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, {change: function(){ ok(true); }});
b.trigger('change');
a.listenTo(b, {change: function(){ ok(false); }});
a.stopListening();
b.trigger('change');
}); });
test("listenTo yourself", 1, function(){ test("listenTo yourself", 1, function(){
@@ -296,6 +259,18 @@ $(document).ready(function() {
obj.trigger('x y'); obj.trigger('x y');
}); });
test("off is chainable", 3, function() {
var obj = _.extend({}, Backbone.Events);
// With no events
ok(obj.off() === obj);
// When removing all events
obj.on('event', function(){}, obj);
ok(obj.off() === obj);
// When removing some events
obj.on('event', function(){}, obj);
ok(obj.off('event') === obj);
});
test("#1310 - off does not skip consecutive events", 0, function() { test("#1310 - off does not skip consecutive events", 0, function() {
var obj = _.extend({}, Backbone.Events); var obj = _.extend({}, Backbone.Events);
obj.on('event', function() { ok(false); }, obj); obj.on('event', function() { ok(false); }, obj);
@@ -425,21 +400,4 @@ $(document).ready(function() {
_.extend({}, Backbone.Events).once('event').trigger('event'); _.extend({}, Backbone.Events).once('event').trigger('event');
}); });
test("event functions are chainable", function() {
var obj = _.extend({}, Backbone.Events);
var obj2 = _.extend({}, Backbone.Events);
var fn = function() {};
equal(obj, obj.trigger('noeventssetyet'));
equal(obj, obj.off('noeventssetyet'));
equal(obj, obj.stopListening('noeventssetyet'));
equal(obj, obj.on('a', fn));
equal(obj, obj.once('c', fn));
equal(obj, obj.trigger('a'));
equal(obj, obj.listenTo(obj2, 'a', fn));
equal(obj, obj.listenToOnce(obj2, 'b', fn));
equal(obj, obj.off('a c'));
equal(obj, obj.stopListening(obj2, 'a'));
equal(obj, obj.stopListening());
});
}); });

View File

@@ -401,7 +401,7 @@ $(document).ready(function() {
if (attrs.admin) return "Can't change admin status."; if (attrs.admin) return "Can't change admin status.";
}; };
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
options.success.call(this, {admin: true}); options.success.call(this, this, {admin: true}, options);
}; };
model.on('invalid', function(model, error) { model.on('invalid', function(model, error) {
lastError = error; lastError = error;
@@ -418,19 +418,6 @@ $(document).ready(function() {
ok(_.isEqual(this.syncArgs.model, doc)); ok(_.isEqual(this.syncArgs.model, doc));
}); });
test("save, fetch, destroy triggers error event when an error occurs", 3, function () {
var model = new Backbone.Model();
model.on('error', function () {
ok(true);
});
model.sync = function (method, model, options) {
options.error();
};
model.save({data: 2, id: 1});
model.fetch();
model.destroy();
});
test("save with PATCH", function() { test("save with PATCH", function() {
doc.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4}); doc.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4});
doc.save(); doc.save();
@@ -448,7 +435,7 @@ $(document).ready(function() {
test("save in positional style", 1, function() { test("save in positional style", 1, function() {
var model = new Backbone.Model(); var model = new Backbone.Model();
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
options.success(); options.success(model, {}, options);
}; };
model.save('title', 'Twelfth Night'); model.save('title', 'Twelfth Night');
equal(model.get('title'), 'Twelfth Night'); equal(model.get('title'), 'Twelfth Night');
@@ -457,8 +444,8 @@ $(document).ready(function() {
test("save with non-object success response", 2, function () { test("save with non-object success response", 2, function () {
var model = new Backbone.Model(); var model = new Backbone.Model();
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
options.success('', options); options.success(model, '', options);
options.success(null, options); options.success(model, null, options);
}; };
model.save({testing:'empty'}, { model.save({testing:'empty'}, {
success: function (model) { success: function (model) {
@@ -733,7 +720,7 @@ $(document).ready(function() {
test("#1030 - `save` with `wait` results in correct attributes if success is called during sync", 2, function() { test("#1030 - `save` with `wait` results in correct attributes if success is called during sync", 2, function() {
var model = new Backbone.Model({x: 1, y: 2}); var model = new Backbone.Model({x: 1, y: 2});
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
options.success(); options.success(model, {}, options);
}; };
model.on("change:x", function() { ok(true); }); model.on("change:x", function() { ok(true); });
model.save({x: 3}, {wait: true}); model.save({x: 3}, {wait: true});
@@ -906,7 +893,7 @@ $(document).ready(function() {
} }
}; };
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
options.success(); options.success(model, {}, options);
}; };
model.save({id: 1}, opts); model.save({id: 1}, opts);
model.fetch(opts); model.fetch(opts);
@@ -915,8 +902,9 @@ $(document).ready(function() {
test("#1412 - Trigger 'sync' event.", 3, function() { test("#1412 - Trigger 'sync' event.", 3, function() {
var model = new Backbone.Model({id: 1}); var model = new Backbone.Model({id: 1});
model.sync = function (method, model, options) { options.success(); }; model.url = '/test';
model.on('sync', function(){ ok(true); }); model.on('sync', function(){ ok(true); });
Backbone.ajax = function(settings){ settings.success(); };
model.fetch(); model.fetch();
model.save(); model.save();
model.destroy(); model.destroy();
@@ -962,7 +950,7 @@ $(document).ready(function() {
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
sync: function(method, model, options) { sync: function(method, model, options) {
setTimeout(function(){ setTimeout(function(){
options.success(); options.success(model, {}, options);
start(); start();
}, 0); }, 0);
} }