text: ﻿// Backbone.BabySitter
  // -------------------
  // v0.0.6
  //
  // Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
  // Distributed under MIT license
  //
  // http://github.com/babysitterjs/backbone.babysitter
  
  (function (root, factory) {
      if (typeof exports === 'object') {
  
          var lodash = require('lodash');
          var backbone = require('backbone');
  
          module.exports = factory(lodash, backbone);
  
      } else if (typeof define === 'function' && define.amd) {
  
          define(['lodash', 'backbone'], factory);
  
      }
  }(this, function (_, Backbone) {
      "option strict";
  
      // Backbone.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();
              },
  
              // 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 it's `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();
              },
  
              // 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 Lo-dash, 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'];
  
          _.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, _);
  
      return Backbone.ChildViewContainer;
  
  }));