rendr
Version:
Render your Backbone.js apps on the client and the server.
134 lines (112 loc) • 3.14 kB
JavaScript
var _ = require('underscore'),
Backbone = require('backbone'),
syncer = require('../syncer'),
BaseModel = require('./model'),
Super = Backbone.Collection,
isServer = (typeof window === 'undefined');
if (!isServer) {
Backbone.$ = window.$ || require('jquery');
}
var BaseCollection = Super.extend({
model: BaseModel,
params: undefined,
meta: undefined,
/**
* Provide the ability to set default params for every 'fetch' call.
*/
defaultParams: null,
constructor: function(models, options) {
/**
* Capture the options as instance variable.
*/
this.options = options || {};
/**
* Store a reference to the app instance.
*/
this.app = this.options.app;
/**
* Store a reference to the params that were used to
* query for these models.
*/
this.params = this.options.params || {};
_.defaults(this.params, this.defaultParams || {});
/**
* Add 'meta' property to store the parts of the response
* that aren't part of the jsonKey.
*/
this.meta = {};
if (_.isObject(this.options.meta)) {
_.extend(this.meta, this.options.meta);
delete this.options.meta;
}
Super.apply(this, arguments);
this.store();
},
/**
* Make sure that `model.app` is set for all operations like
* `this.add()`, `this.reset()`, `this.set()`, `this.push()`, etc.
*/
_prepareModel: function() {
var model;
model = Super.prototype._prepareModel.apply(this, arguments);
model.app = this.app;
return model;
},
/**
* Idempotent parse
*/
parse: function(resp, modifyInstance) {
var jsonResp, meta, parsed;
if (modifyInstance == null) {
modifyInstance = true;
}
if (resp != null && this.jsonKey && (jsonResp = resp[this.jsonKey])) {
if (modifyInstance) {
meta = _.omit(resp, this.jsonKey);
_.extend(this.meta, meta);
}
parsed = jsonResp;
} else {
parsed = resp;
}
return this.parseModels(parsed);
},
parseModels: function(resp) {
var jsonKey, jsonKeyResp;
resp = _.clone(resp);
jsonKey = this.model.prototype.jsonKey;
_.each(resp, function(modelResp, i) {
jsonKeyResp = modelResp[jsonKey];
if (jsonKeyResp) {
resp[i] = jsonKeyResp;
}
});
return resp;
},
fetch: function(options) {
options = options || {};
// Each time new models are fetched, store the params used.
if (options.data) {
_.defaults(options.data, this.defaultParams || {});
this.params = options.data;
}
return Super.prototype.fetch.apply(this, arguments);
},
/**
* Instance method to store the collection and its models.
*/
store: function() {
if (this.app && this.app.fetcher) {
this.each(function(model) {
model.store();
});
this.app.fetcher.collectionStore.set(this);
}
}
});
/**
* Mix-in the `syncer`, shared between `BaseModel` and `BaseCollection`, which
* encapsulates logic for fetching data from the API.
*/
_.extend(BaseCollection.prototype, syncer);
module.exports = BaseCollection;