Guest User

Untitled

a guest
Nov 24th, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.69 KB | None | 0 0
  1. /*
  2. @author Simon Schmid (sled)
  3. @date 05/312011
  4. @class Backbone.Subset
  5. @name Backbone Subset
  6. @desc
  7. Implements an imaginary subset of a Backbone Collection (as superset)
  8. */
  9.  
  10.  
  11. // Extend the default Backbone.Collection
  12.  
  13. _.extend(Backbone.Collection.prototype, {
  14.  
  15. build: function (attrs) {
  16. var model = new this.model(attrs);
  17. this.add(model);
  18. return model;
  19. },
  20. merge: function (collection) {
  21. this.add(collection.models);
  22. return this
  23. }
  24. });
  25.  
  26.  
  27. // Standard Constructor
  28. Backbone.Subset = function(options) {
  29.  
  30.  
  31. this.options = options || (options={});
  32.  
  33. // use the comparator supplied by the options
  34. if(options.comparator) {
  35. this.comparator = options.comparator;
  36. delete options.comparator;
  37. }
  38.  
  39. if(!options.superset) { throw 'Subset must belong to a superset!'; }
  40. if(!options.filter) { throw 'Subset must have a filter'; }
  41. if(!(options.superset instanceof Backbone.Collection) && !(options.superset instanceof Backbone.Subset)) {
  42. throw "Subset must have Backbone.Collection or Backbone.Subset as its superset!";
  43. }
  44.  
  45. var self = this;
  46.  
  47. // transform method, to be applied on models
  48. this.transform = options.transform || function(echo) { return echo; };
  49. this.filter = options.filter;
  50. this.superset = options.superset;
  51.  
  52. // hook on superset's events
  53. this.superset.bind("all", function(ev) {
  54.  
  55.  
  56. switch(ev) {
  57. case "add":
  58. case "remove":
  59. if(self.filter(arguments[1])) {
  60. // we are affected, forward events on this subset
  61. self.trigger.apply(self,arguments);
  62. }
  63. break;
  64. case "refresh":
  65. break;
  66. default:
  67. // model has changed, maybe it doesn't belong in this subset anymore
  68. if(ev.indexOf("change:") === 0) {
  69.  
  70. // sub collection already has object so it could be removed
  71. if(self.get(arguments[1])) {
  72.  
  73. // maybe trigger remove
  74. if(!self.filter(arguments[1])) {
  75. self.trigger('remove', arguments[1], self);
  76. }
  77. else
  78. {
  79. // still in the set, forward event to this subset
  80. self.trigger.apply(self, arguments);
  81. }
  82. }
  83.  
  84. // we got a new element, yay!
  85. if(!self.get(arguments[0]) && self.filter(arguments[1])) {
  86. this.trigger('add', arguments[1], self);
  87. }
  88. }
  89.  
  90. }
  91.  
  92. // always refresh the models
  93. self._reset();
  94. });
  95.  
  96. // remove crucial entries from options
  97. delete options.filter
  98. delete options.superset;
  99.  
  100. // get an event if a model changes
  101. this._boundOnModelEvent = _.bind(this._onModelEvent, this);
  102.  
  103. // refresh the models
  104. this._reset();
  105.  
  106. // call custom constructor
  107. this.initialize(options);
  108. };
  109.  
  110.  
  111.  
  112.  
  113. _.extend(Backbone.Subset.prototype, Backbone.Collection.prototype, {
  114.  
  115. // array holding the models as json objects
  116. toJSON: function() {
  117. return this.map(function(c) {
  118. return c.toJSON();
  119. })
  120. },
  121.  
  122. // add models
  123. add: function(models, options) {
  124.  
  125. var self = this;
  126.  
  127. models = _.filter(models, this.filter);
  128.  
  129. // return if no models resist
  130. if(models.length == 0) { return; }
  131.  
  132. // actually add the models to the superset
  133. this.superset.add(models, options);
  134. return this;
  135. },
  136.  
  137. // remove models
  138. remove: function(models, options) {
  139. // remove model from superset
  140. this.superset.remove(_.filter(_.filter(models, function(cm) {
  141. return m != null;
  142. }), this.filter), options);
  143. },
  144.  
  145. // get a certain model by id!
  146. get: function(model_id) {
  147. return _.select(this.models, function(cm) {
  148. return cm.id == model_id;
  149. })[0]
  150. },
  151.  
  152. // get a certain model by cid !
  153. getByCid: function(model_cid) {
  154. return _.select(this.models, function(cm) {
  155. return cm.cid == model_cid;
  156. })[0]
  157. },
  158.  
  159. // get a model at a certain position in the _subset_
  160. at: function(index) {
  161. return this.models[index]
  162. },
  163.  
  164. // sorting
  165. sort: function(options) {
  166. this.superset.sort(options);
  167. return this;
  168. },
  169.  
  170. // pluck an attribute from each model in the subset
  171. pluck: function(attr) {
  172. return _.map(this.models, function(model) {
  173. return model.get(m)
  174. })
  175. },
  176.  
  177. // refresh the superset (triggers event to refresh this one too)
  178. refresh: function(models, options) {
  179. this.superset.refresh(models, options);
  180. return this;
  181. },
  182.  
  183. fetch: function(options) {
  184. this.superset.fetch(options);
  185. return this;
  186. },
  187.  
  188. create: function(model, options) {
  189. return this.superset.create(model, options);
  190. },
  191.  
  192. parse: function(resp) {
  193. return resp;
  194. },
  195.  
  196. length: function() {
  197. this._reset();
  198. return this.models.length;
  199. },
  200.  
  201. chain: function() {
  202. return this.superset.chain();
  203. },
  204.  
  205. // reset state and refresh the models
  206. _reset: function() {
  207. this.model = this.options.model || this.superset.model;
  208. this.models = this._models();
  209. },
  210.  
  211. // get the models which belong to this collection
  212. _models: function() {
  213. // using internal filter method to filter the models that belong to this subset
  214. return _.filter(_.filter(this.transform(this.superset.models), function(cm) {
  215. return cm != null;
  216. }), this.filter);
  217. }
  218.  
  219. });
  220.  
  221.  
  222. var subsetMethods = ["forEach", "each", "map", "reduce", "reduceRight", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "invoke", "max", "min", "sortBy", "sortedIndex", "toArray", "size", "first", "rest", "last", "without", "indexOf", "lastIndexOf", "isEmpty"];
  223.  
  224. // add common function to this subset
  225.  
  226. _.each(subsetMethods, function(cMethod) {
  227. Backbone.Subset.prototype[cMethod] = function() {
  228. return _[cMethod].apply(_, [this._models()].concat(_.toArray(arguments)))
  229. };
  230. });
Add Comment
Please, Sign In to add comment