Permalink
Browse files

Merge remote-tracking branch 'masylum/master'

Also updated dependency versions.

Conflicts:
	backbone.subset.js
	test/test.js
  • Loading branch information...
Steven Lindberg
Steven Lindberg committed May 9, 2012
2 parents 481bed1 + d9bbfa2 commit 84f19539d5ab458184779b158651e31f48304407
Showing with 313 additions and 441 deletions.
  1. +96 −61 backbone.subset.js
  2. +1 −1 package.json
  3. +216 −379 test/test.js
View
@@ -5,7 +5,18 @@
*/
(function () {
- var Subset = {}
+ var Subset = {};
+
+ /**
+ * Returns the xor of two sets
+ *
+ * @param {Array} a
+ * @param {Array} b
+ * @return {Array}
+ */
+ function xor(a, b) {
+ return _.difference(_.union(a, b), _.intersection(a, b));
+ }
/**
* Subset constructor
@@ -29,23 +40,23 @@
this.comparator = this.comparator || options.comparator || parent.comparator;
this.liveupdate_keys = this.liveupdate_keys || options.liveupdate_keys || 'none';
- _.bindAll(this, '_onModelEvent', '_unbindModelEvents', '_proxyEvents');
+ _.bindAll(this, '_onModelEvent', '_unbindModelEvents', '_proxyAdd'
+ , '_proxyReset', '_proxyRemove', '_proxyChange');
- parent.bind('all', this._proxyEvents);
+ parent.bind('add', this._proxyAdd);
+ parent.bind('remove', this._proxyRemove);
+ parent.bind('reset', this._proxyReset);
+ parent.bind('all', this._proxyChange);
if (this.beforeInitialize) {
this.beforeInitialize.apply(this, arguments);
}
if (!options.no_reset) {
this._reset();
-
- if (models) {
- this.reset(models, {silent: true});
- }
- }
- else {
- this._resetSubset(parent.models, {silent: true});
+ this.reset(models || parent.models, {silent: true});
+ } else {
+ this._resetSubset({silent: true});
}
this.initialize.apply(this, arguments);
@@ -61,22 +72,28 @@
Subset.reset = function (models, options) {
var parent = _.result(this, 'parent')
, parent_models = _.clone(parent.models)
- , ids = _(parent_models).pluck('id');
+ , xored_ids
+ , ids = this.pluck('id');
models = models || [];
models = _.isArray(models) ? models : [models];
options = options || {};
+ // delete parent reseted models
+ parent_models = _.reject(parent_models, function (model) {
+ return _.include(ids, model.id);
+ });
+
// insert parent reseted models
_.each(models, function (model) {
- if (ids.indexOf(model.id) === -1) {
- parent_models.push(model);
- }
- }, this);
+ parent_models.push(model);
+ });
- parent.reset(parent_models, _.extend(options, {subset_reset: true}));
+ // xored ids are the ones added/removed
+ xored_ids = xor(ids, _.pluck(models, 'id'));
- this._resetSubset(models, options);
+ parent.reset(parent_models, _.extend(options, {silent: true}));
+ parent.trigger('reset', this, {model_ids: xored_ids});
return this;
};
@@ -92,7 +109,7 @@
var changed = false;
// re-evaluate each model's eligibility
- this._parent.each(function (model) {
+ _.result(this, 'parent').each(function (model) {
changed |= this._updateModelMembership(model);
}, this);
@@ -111,14 +128,12 @@
* @param {Object} options
* @return {Object} collection
*/
- Subset._resetSubset = function (models, options) {
- models = models || [];
- models = _.isArray(models) ? models : [models];
+ Subset._resetSubset = function (options) {
options = options || {};
this.each(this._unbindModelEvents);
this._reset();
- _(models).each(function (model) {
+ _.result(this, 'parent').each(function (model) {
this._addToSubset(model, {silent: true});
}, this);
@@ -148,23 +163,6 @@
* @return {Object} model
*/
Subset._addToSubset = function (model, options) {
- var parent = _.result(this, 'parent')
- , parents_model;
-
- if (model.id && (parents_model = parent.get(model.id))) {
- if (!(model instanceof Backbone.Model)) {
- parents_model.set(model, {silent: true});
- model = parents_model;
- }
- else {
- parents_model.set(model.attributes, {silent: true});
- model = parents_model;
- }
- }
- else {
- model = Backbone.Collection.prototype._prepareModel.call(this, model, options);
- }
-
if (this.sieve(model)) {
return Backbone.Collection.prototype.add.call(this, model, options);
}
@@ -217,35 +215,72 @@
};
/**
- * Proxies an event happening into the parent collection to the Subset
+ * Proxies an `add` event happening into the parent collection to the Subset
*
* @param {Object} model
+ * @param {Object} collection
* @param {Object} options
- * @return {Object} model
*/
- Subset._proxyEvents = function (ev, model, collection, options) {
- if (collection !== this) {
- if (ev === 'change' && this.liveupdate_keys === 'all') {
- this._updateModelMembership(model);
- } else if (ev.slice(0, 7) === 'change:' && _.isArray(this.liveupdate_keys)
- && _.include(this.liveupdate_keys, ev.slice(7))) {
- this._updateModelMembership(model);
- }
+ Subset._proxyAdd = function (model, collection, options) {
+ options = options || {};
- if (ev === 'add' && this.sieve(model) && !options.noproxy) {
- this._addToSubset(model, options);
- }
+ if (collection !== this && this.sieve(model) && !options.noproxy) {
+ this._addToSubset(model, options);
+ }
+ };
- if (ev === 'remove' && this.sieve(model) && !options.noproxy) {
- this._removeFromSubset(model, options);
- }
+ /**
+ * Proxies a `remove` event happening into the parent collection to the Subset
+ *
+ * @param {Object} model
+ * @param {Object} collection
+ * @param {Object} options
+ */
+ Subset._proxyRemove = function (model, collection, options) {
+ options = options || {};
+
+ if (collection !== this && this.sieve(model) && !options.noproxy) {
+ this._removeFromSubset(model, options);
}
+ };
- // model == collection
- if (ev === 'reset' && model !== this) {
- if (!collection.subset_reset) {
- this._resetSubset(model.models, collection);
- }
+ /**
+ * Proxies a `change` event happening into the parent collection to the Subset
+ *
+ * @param {Object} ev
+ * @param {Object} model
+ * @param {Object} collection
+ */
+ Subset._proxyChange = function (ev, model, collection) {
+ if (collection !== this && ev === 'change' && this.liveupdate_keys === 'all') {
+ this._updateModelMembership(model);
+ } else if (ev.slice(0, 7) === 'change:' && _.isArray(this.liveupdate_keys)
+ && _.include(this.liveupdate_keys, ev.slice(7))) {
+ this._updateModelMembership(model);
+ }
+ };
+
+ /**
+ * Proxies a `reset` event happening into the parent collection to the Subset
+ *
+ * @param {Object} collection
+ * @param {Object} options
+ */
+ Subset._proxyReset = function (collection, options) {
+ options = options || {};
+ var ids
+ , sieved_ids
+ , self = this;
+
+ if (options.model_ids) {
+ ids = _.intersection(this.pluck('id'), options.model_ids);
+ sieved_ids = _.pluck(_.filter(ids, function (id) {
+ return self.sieve(self.get(id));
+ }), 'id');
+ }
+
+ if ((!options.model_ids || this === collection || sieved_ids.length) && (!options || !options.noproxy)) {
+ this._resetSubset(_.extend(_.clone(options), {proxied: true}));
}
};
@@ -286,4 +321,4 @@
_.extend(Backbone.Subset.prototype, Backbone.Collection.prototype, Subset);
Backbone.Subset.extend = Backbone.Collection.extend;
-}).call(this);
+}());
View
@@ -5,6 +5,6 @@
"author": "Pau ramon <masylum@gmail.com>",
"contributors": ["Saimon Moore <saimon@saimonmoore.net>", "Philip Roberts <phil@latentflip.com>"],
"repository": {"type": "git", "url": "git://github.com/masylum/Backbone.Subset.git"},
- "devDependencies": {"backbone": "0.5.3", "underscore": "*", "mocha": "*"},
+ "devDependencies": {"backbone": "0.9.1", "underscore": "1.3.3", "mocha": "*"},
"main": "./backbone.subset"
}
Oops, something went wrong.

0 comments on commit 84f1953

Please sign in to comment.