File: ../src/filteredcollection.js
define([
'aeris/util',
'aeris/collection',
'aeris/errors/invalidargumenterror'
], function(_, Collection, InvalidArgumentError) {
/**
* A FilteredCollection acts as a subset of some
* 'source' collection. It is bound to the models in it's
* source collection, though only models which pass a
* defined filter will be set on the FilteredCollection.
*
* @class aeris.FilteredCollection
* @extends aeris.Collection
*
* @constructor
* @override
*
* @param {Array.<aeris.Model>=} opt_models
*
* @param {Object=} opt_options
* @param {function():Boolean} opt_options.filter The filter to use when binding to the source collection.
*/
var FilteredCollection = function(opt_models, opt_options) {
var options = _.defaults(opt_options || {}, {
filter: function() { return true; }
});
/**
* @property sourceCollection_
* @private
* @type {aeris.Collection}
*/
this.sourceCollection_ = options.source;
Collection.call(this, opt_models, options);
this.ensureSourceCollection_();
this.setFilter(options.filter);
this.updateModelsFromSource_();
this.bindToSourceCollection_();
};
_.inherits(FilteredCollection, Collection);
/**
* Filters the collection, using models from the
* source collection.
*
* Filter will continue to be used when keeping the
* FilteredCollection in sync with its source collection.
*
* @method setFilter
* @param {function(aeris.Model):Boolean} filter
* @param {Object=} opt_ctx Context for filter function.
*/
FilteredCollection.prototype.setFilter = function(filter, opt_ctx) {
var ctx = opt_ctx || this;
this.filter_ = _.bind(filter, ctx);
this.updateModelsFromSource_();
};
/**
* @method ensureSourceCollection_
* @private
* @throws {aeris.errors.InvalidArgumentError}
*/
FilteredCollection.prototype.ensureSourceCollection_ = function() {
if (!(this.sourceCollection_ instanceof Collection)) {
throw new InvalidArgumentError(this.sourceCollection_ + ' is not ' +
'a valid source for a FilteredCollection');
}
};
/**
* @method bindToSourceCollection_
* @private
*/
FilteredCollection.prototype.bindToSourceCollection_ = function() {
this.listenTo(this.sourceCollection_, {
'add remove reset': this.updateModelsFromSource_
});
};
/**
* @method updateModelsFromSource_
* @private
*/
FilteredCollection.prototype.updateModelsFromSource_ = function() {
var filteredModels = this.sourceCollection_.filter(this.filter_);
this.set(filteredModels);
};
return FilteredCollection;
});