PageRenderTime 33ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/web/public/js/lib/backbone.babysitter.js

https://bitbucket.org/synapsos/lounge-old
JavaScript | 213 lines | 116 code | 45 blank | 52 comment | 17 complexity | 758d22ace357b175d3ac4111c01de1a8 MD5 | raw file
  1. // Backbone.BabySitter, v0.0.4
  2. // Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
  3. // Distributed under MIT license
  4. // http://github.com/marionettejs/backbone.babysitter
  5. (function (root, factory) {
  6. if (typeof exports === 'object') {
  7. var underscore = require('underscore');
  8. var backbone = require('backbone');
  9. module.exports = factory(underscore, backbone);
  10. } else if (typeof define === 'function' && define.amd) {
  11. define(['underscore', 'backbone'], factory);
  12. }
  13. }(this, function (_, Backbone) {
  14. "option strict";
  15. // Backbone.ChildViewContainer
  16. // ---------------------------
  17. //
  18. // Provide a container to store, retrieve and
  19. // shut down child views.
  20. Backbone.ChildViewContainer = (function(Backbone, _){
  21. // Container Constructor
  22. // ---------------------
  23. var Container = function(initialViews){
  24. this._views = {};
  25. this._indexByModel = {};
  26. this._indexByCollection = {};
  27. this._indexByCustom = {};
  28. this._updateLength();
  29. this._addInitialViews(initialViews);
  30. };
  31. // Container Methods
  32. // -----------------
  33. _.extend(Container.prototype, {
  34. // Add a view to this container. Stores the view
  35. // by `cid` and makes it searchable by the model
  36. // and/or collection of the view. Optionally specify
  37. // a custom key to store an retrieve the view.
  38. add: function(view, customIndex){
  39. var viewCid = view.cid;
  40. // store the view
  41. this._views[viewCid] = view;
  42. // index it by model
  43. if (view.model){
  44. this._indexByModel[view.model.cid] = viewCid;
  45. }
  46. // index it by collection
  47. if (view.collection){
  48. this._indexByCollection[view.collection.cid] = viewCid;
  49. }
  50. // index by custom
  51. if (customIndex){
  52. this._indexByCustom[customIndex] = viewCid;
  53. }
  54. this._updateLength();
  55. },
  56. // Find a view by the model that was attached to
  57. // it. Uses the model's `cid` to find it, and
  58. // retrieves the view by it's `cid` from the result
  59. findByModel: function(model){
  60. var viewCid = this._indexByModel[model.cid];
  61. return this.findByCid(viewCid);
  62. },
  63. // Find a view by the collection that was attached to
  64. // it. Uses the collection's `cid` to find it, and
  65. // retrieves the view by it's `cid` from the result
  66. findByCollection: function(col){
  67. var viewCid = this._indexByCollection[col.cid];
  68. return this.findByCid(viewCid);
  69. },
  70. // Find a view by a custom indexer.
  71. findByCustom: function(index){
  72. var viewCid = this._indexByCustom[index];
  73. return this.findByCid(viewCid);
  74. },
  75. // Find by index. This is not guaranteed to be a
  76. // stable index.
  77. findByIndex: function(index){
  78. return _.values(this._views)[index];
  79. },
  80. // retrieve a view by it's `cid` directly
  81. findByCid: function(cid){
  82. return this._views[cid];
  83. },
  84. // Remove a view
  85. remove: function(view){
  86. var viewCid = view.cid;
  87. // delete model index
  88. if (view.model){
  89. delete this._indexByModel[view.model.cid];
  90. }
  91. // delete collection index
  92. if (view.collection){
  93. delete this._indexByCollection[view.collection.cid];
  94. }
  95. // delete custom index
  96. var cust;
  97. for (var key in this._indexByCustom){
  98. if (this._indexByCustom.hasOwnProperty(key)){
  99. if (this._indexByCustom[key] === viewCid){
  100. cust = key;
  101. break;
  102. }
  103. }
  104. }
  105. if (cust){
  106. delete this._indexByCustom[cust];
  107. }
  108. // remove the view from the container
  109. delete this._views[viewCid];
  110. // update the length
  111. this._updateLength();
  112. },
  113. // Call a method on every view in the container,
  114. // passing parameters to the call method one at a
  115. // time, like `function.call`.
  116. call: function(method, args){
  117. args = Array.prototype.slice.call(arguments, 1);
  118. this.apply(method, args);
  119. },
  120. // Apply a method on every view in the container,
  121. // passing parameters to the call method one at a
  122. // time, like `function.apply`.
  123. apply: function(method, args){
  124. var view;
  125. // fix for IE < 9
  126. args = args || [];
  127. _.each(this._views, function(view, key){
  128. if (_.isFunction(view[method])){
  129. view[method].apply(view, args);
  130. }
  131. });
  132. },
  133. // Update the `.length` attribute on this container
  134. _updateLength: function(){
  135. this.length = _.size(this._views);
  136. },
  137. // set up an initial list of views
  138. _addInitialViews: function(views){
  139. if (!views){ return; }
  140. var view, i,
  141. length = views.length;
  142. for (i=0; i<length; i++){
  143. view = views[i];
  144. this.add(view);
  145. }
  146. }
  147. });
  148. // Borrowing this code from Backbone.Collection:
  149. // http://backbonejs.org/docs/backbone.html#section-106
  150. //
  151. // Mix in methods from Underscore, for iteration, and other
  152. // collection related features.
  153. var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
  154. 'select', 'reject', 'every', 'all', 'some', 'any', 'include',
  155. 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
  156. 'last', 'without', 'isEmpty', 'pluck'];
  157. _.each(methods, function(method) {
  158. Container.prototype[method] = function() {
  159. var views = _.values(this._views);
  160. var args = [views].concat(_.toArray(arguments));
  161. return _[method].apply(_, args);
  162. };
  163. });
  164. // return the public API
  165. return Container;
  166. })(Backbone, _);
  167. return Backbone.ChildViewContainer;
  168. }));