// Backbone.BabySitter // ------------------- // v1.0.0 // // Copyright (c)2019 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, _.bind(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){ return this._add(view, customIndex) ._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 its `cid` directly findByCid: function(cid){ return this._views[cid]; }, // Remove a view remove: function(view){ return this._remove(view) ._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, _.toArray(arguments).slice(1)); }, // 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); return this; }, // To be used when avoiding call _updateLength // When you are done adding all your new views // call _updateLength _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; } return this; }, // To be used when avoiding call _updateLength // When you are done adding all your new views // call _updateLength _remove: function (view){ var viewCid = view.cid; // delete model index if (view.model){ delete this._indexByModel[view.model.cid]; } // delete custom index _.some(this._indexByCustom, _.bind(function(cid, key) { if (cid === viewCid) { delete this._indexByCustom[key]; return true; } }, this)); // remove the view from the container delete this._views[viewCid]; return this; } }); // 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 = '1.0.0'; Backbone.ChildViewContainer.noConflict = function () { Backbone.ChildViewContainer = previousChildViewContainer; return this; }; return Backbone.ChildViewContainer; }));