5 // Copyright (c)2014 Derick Bailey, Muted Solutions, LLC.
6 // Distributed under MIT license
8 // http://github.com/marionettejs/backbone.babysitter
10 (function(root, factory) {
12 if (typeof define === 'function' && define.amd) {
13 define(['backbone', 'underscore'], function(Backbone, _) {
14 return factory(Backbone, _);
16 } else if (typeof exports !== 'undefined') {
17 var Backbone = require('backbone');
18 var _ = require('underscore');
19 module.exports = factory(Backbone, _);
21 factory(root.Backbone, root._);
24 }(this, function(Backbone, _) {
27 var previousChildViewContainer = Backbone.ChildViewContainer;
29 // BabySitter.ChildViewContainer
30 // -----------------------------
32 // Provide a container to store, retrieve and
33 // shut down child views.
35 Backbone.ChildViewContainer = (function (Backbone, _) {
37 // Container Constructor
38 // ---------------------
40 var Container = function(views){
42 this._indexByModel = {};
43 this._indexByCustom = {};
46 _.each(views, this.add, this);
52 _.extend(Container.prototype, {
54 // Add a view to this container. Stores the view
55 // by `cid` and makes it searchable by the model
56 // cid (and model itself). Optionally specify
57 // a custom key to store an retrieve the view.
58 add: function(view, customIndex){
59 var viewCid = view.cid;
62 this._views[viewCid] = view;
66 this._indexByModel[view.model.cid] = viewCid;
71 this._indexByCustom[customIndex] = viewCid;
78 // Find a view by the model that was attached to
79 // it. Uses the model's `cid` to find it.
80 findByModel: function(model){
81 return this.findByModelCid(model.cid);
84 // Find a view by the `cid` of the model that was attached to
85 // it. Uses the model's `cid` to find the view `cid` and
86 // retrieve the view using it.
87 findByModelCid: function(modelCid){
88 var viewCid = this._indexByModel[modelCid];
89 return this.findByCid(viewCid);
92 // Find a view by a custom indexer.
93 findByCustom: function(index){
94 var viewCid = this._indexByCustom[index];
95 return this.findByCid(viewCid);
98 // Find by index. This is not guaranteed to be a
100 findByIndex: function(index){
101 return _.values(this._views)[index];
104 // retrieve a view by its `cid` directly
105 findByCid: function(cid){
106 return this._views[cid];
110 remove: function(view){
111 var viewCid = view.cid;
113 // delete model index
115 delete this._indexByModel[view.model.cid];
118 // delete custom index
119 _.any(this._indexByCustom, function(cid, key) {
120 if (cid === viewCid) {
121 delete this._indexByCustom[key];
126 // remove the view from the container
127 delete this._views[viewCid];
130 this._updateLength();
134 // Call a method on every view in the container,
135 // passing parameters to the call method one at a
136 // time, like `function.call`.
137 call: function(method){
138 this.apply(method, _.tail(arguments));
141 // Apply a method on every view in the container,
142 // passing parameters to the call method one at a
143 // time, like `function.apply`.
144 apply: function(method, args){
145 _.each(this._views, function(view){
146 if (_.isFunction(view[method])){
147 view[method].apply(view, args || []);
152 // Update the `.length` attribute on this container
153 _updateLength: function(){
154 this.length = _.size(this._views);
158 // Borrowing this code from Backbone.Collection:
159 // http://backbonejs.org/docs/backbone.html#section-106
161 // Mix in methods from Underscore, for iteration, and other
162 // collection related features.
163 var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
164 'select', 'reject', 'every', 'all', 'some', 'any', 'include',
165 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
166 'last', 'without', 'isEmpty', 'pluck'];
168 _.each(methods, function(method) {
169 Container.prototype[method] = function() {
170 var views = _.values(this._views);
171 var args = [views].concat(_.toArray(arguments));
172 return _[method].apply(_, args);
176 // return the public API
181 Backbone.ChildViewContainer.VERSION = '0.1.4';
183 Backbone.ChildViewContainer.noConflict = function () {
184 Backbone.ChildViewContainer = previousChildViewContainer;
188 return Backbone.ChildViewContainer;