You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.2 KiB
JavaScript
191 lines
5.2 KiB
JavaScript
// Backbone.BabySitter
|
|
// -------------------
|
|
// v0.1.6
|
|
//
|
|
// Copyright (c)2015 Derick Bailey, Muted Solutions, LLC.
|
|
// Distributed under MIT license
|
|
//
|
|
// http://github.com/marionettejs/backbone.babysitter
|
|
|
|
(function(root, factory) {
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
define(['backbone', 'underscore'], function(Backbone, _) {
|
|
return factory(Backbone, _);
|
|
});
|
|
} else if (typeof exports !== 'undefined') {
|
|
var Backbone = require('backbone');
|
|
var _ = require('underscore');
|
|
module.exports = factory(Backbone, _);
|
|
} else {
|
|
factory(root.Backbone, root._);
|
|
}
|
|
|
|
}(this, function(Backbone, _) {
|
|
'use strict';
|
|
|
|
var previousChildViewContainer = Backbone.ChildViewContainer;
|
|
|
|
// BabySitter.ChildViewContainer
|
|
// -----------------------------
|
|
//
|
|
// Provide a container to store, retrieve and
|
|
// shut down child views.
|
|
|
|
Backbone.ChildViewContainer = (function (Backbone, _) {
|
|
|
|
// Container Constructor
|
|
// ---------------------
|
|
|
|
var Container = function(views){
|
|
this._views = {};
|
|
this._indexByModel = {};
|
|
this._indexByCustom = {};
|
|
this._updateLength();
|
|
|
|
_.each(views, this.add, this);
|
|
};
|
|
|
|
// Container Methods
|
|
// -----------------
|
|
|
|
_.extend(Container.prototype, {
|
|
|
|
// Add a view to this container. Stores the view
|
|
// by `cid` and makes it searchable by the model
|
|
// cid (and model itself). Optionally specify
|
|
// a custom key to store an retrieve the view.
|
|
add: function(view, customIndex){
|
|
var viewCid = view.cid;
|
|
|
|
// store the view
|
|
this._views[viewCid] = view;
|
|
|
|
// index it by model
|
|
if (view.model){
|
|
this._indexByModel[view.model.cid] = viewCid;
|
|
}
|
|
|
|
// index by custom
|
|
if (customIndex){
|
|
this._indexByCustom[customIndex] = viewCid;
|
|
}
|
|
|
|
this._updateLength();
|
|
return this;
|
|
},
|
|
|
|
// Find a view by the model that was attached to
|
|
// it. Uses the model's `cid` to find it.
|
|
findByModel: function(model){
|
|
return this.findByModelCid(model.cid);
|
|
},
|
|
|
|
// Find a view by the `cid` of the model that was attached to
|
|
// it. Uses the model's `cid` to find the view `cid` and
|
|
// retrieve the view using it.
|
|
findByModelCid: function(modelCid){
|
|
var viewCid = this._indexByModel[modelCid];
|
|
return this.findByCid(viewCid);
|
|
},
|
|
|
|
// Find a view by a custom indexer.
|
|
findByCustom: function(index){
|
|
var viewCid = this._indexByCustom[index];
|
|
return this.findByCid(viewCid);
|
|
},
|
|
|
|
// Find by index. This is not guaranteed to be a
|
|
// stable index.
|
|
findByIndex: function(index){
|
|
return _.values(this._views)[index];
|
|
},
|
|
|
|
// retrieve a view by its `cid` directly
|
|
findByCid: function(cid){
|
|
return this._views[cid];
|
|
},
|
|
|
|
// Remove a view
|
|
remove: function(view){
|
|
var viewCid = view.cid;
|
|
|
|
// delete model index
|
|
if (view.model){
|
|
delete this._indexByModel[view.model.cid];
|
|
}
|
|
|
|
// delete custom index
|
|
_.any(this._indexByCustom, function(cid, key) {
|
|
if (cid === viewCid) {
|
|
delete this._indexByCustom[key];
|
|
return true;
|
|
}
|
|
}, this);
|
|
|
|
// remove the view from the container
|
|
delete this._views[viewCid];
|
|
|
|
// update the length
|
|
this._updateLength();
|
|
return this;
|
|
},
|
|
|
|
// Call a method on every view in the container,
|
|
// passing parameters to the call method one at a
|
|
// time, like `function.call`.
|
|
call: function(method){
|
|
this.apply(method, _.tail(arguments));
|
|
},
|
|
|
|
// Apply a method on every view in the container,
|
|
// passing parameters to the call method one at a
|
|
// time, like `function.apply`.
|
|
apply: function(method, args){
|
|
_.each(this._views, function(view){
|
|
if (_.isFunction(view[method])){
|
|
view[method].apply(view, args || []);
|
|
}
|
|
});
|
|
},
|
|
|
|
// Update the `.length` attribute on this container
|
|
_updateLength: function(){
|
|
this.length = _.size(this._views);
|
|
}
|
|
});
|
|
|
|
// Borrowing this code from Backbone.Collection:
|
|
// http://backbonejs.org/docs/backbone.html#section-106
|
|
//
|
|
// Mix in methods from Underscore, for iteration, and other
|
|
// collection related features.
|
|
var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
|
|
'select', 'reject', 'every', 'all', 'some', 'any', 'include',
|
|
'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
|
|
'last', 'without', 'isEmpty', 'pluck', 'reduce'];
|
|
|
|
_.each(methods, function(method) {
|
|
Container.prototype[method] = function() {
|
|
var views = _.values(this._views);
|
|
var args = [views].concat(_.toArray(arguments));
|
|
return _[method].apply(_, args);
|
|
};
|
|
});
|
|
|
|
// return the public API
|
|
return Container;
|
|
})(Backbone, _);
|
|
|
|
|
|
Backbone.ChildViewContainer.VERSION = '0.1.6';
|
|
|
|
Backbone.ChildViewContainer.noConflict = function () {
|
|
Backbone.ChildViewContainer = previousChildViewContainer;
|
|
return this;
|
|
};
|
|
|
|
return Backbone.ChildViewContainer;
|
|
|
|
}));
|