PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/backbone-pubnub.js

https://github.com/colincarr/pubnub-backbone
JavaScript | 273 lines | 264 code | 8 blank | 1 comment | 29 complexity | 30c9a39a63ea113fa40557d33e6286b8 MD5 | raw file
  1. /*! pubnub-backbone - v0.1.8 - 2013-10-23 | (c) 2013 PubNub MIT License https://github.com/pubnub/backbone/blob/master/LICENSE */
  2. (function() {
  3. var _sync;
  4. Backbone.PubNub = function(ref, name) {
  5. var _this = this;
  6. this.name = name;
  7. this.ref = ref;
  8. this.uuid = this.ref.uuid();
  9. this.channel = "backbone-" + this.name;
  10. this.records = [];
  11. return this.ref.subscribe({
  12. channel: this.channel,
  13. callback: function(message) {
  14. if (message.uuid !== _this.uuid) {
  15. switch (message.method) {
  16. case "create":
  17. return _this.create(message.model);
  18. case "update":
  19. return _this.update(message.model);
  20. case "delete":
  21. return _this.destroy(message.model);
  22. }
  23. }
  24. }
  25. });
  26. };
  27. _.extend(Backbone.PubNub.prototype, {
  28. publish: function(method, model, options) {
  29. var message;
  30. message = {
  31. method: method,
  32. model: model,
  33. options: options,
  34. uuid: this.uuid
  35. };
  36. return this.ref.publish({
  37. channel: this.channel,
  38. message: message
  39. });
  40. },
  41. read: function(model) {
  42. if (model.id == null) {
  43. return this.find(model.id);
  44. } else {
  45. return this.findAll();
  46. }
  47. },
  48. find: function(id) {
  49. return _.find(this.records, function(record) {
  50. return record.id === id;
  51. });
  52. },
  53. findAll: function() {
  54. return this.records;
  55. },
  56. create: function(model) {
  57. if (model.id == null) {
  58. model.id = this.ref.uuid();
  59. model.set(model.idAttribute, model.id);
  60. }
  61. this.records.push(model);
  62. this.publish("create", model);
  63. return model;
  64. },
  65. update: function(model) {
  66. var oldModel;
  67. oldModel = this.find(model.id);
  68. this.records[this.records.indexOf(oldModel)] = model;
  69. this.publish("update", model);
  70. return model;
  71. },
  72. destroy: function(model) {
  73. if (model.isNew()) {
  74. return false;
  75. }
  76. this.records = _.reject(this.records, function(record) {
  77. return record.id === model.id;
  78. });
  79. this.publish("delete", model);
  80. return model;
  81. }
  82. });
  83. Backbone.PubNub.sync = function(method, model, options) {
  84. var error, errorMessage, pubnub, resp, _ref;
  85. pubnub = (_ref = model.pubnub) != null ? _ref : model.collection.pubnub;
  86. console.log(method, model, options, pubnub);
  87. try {
  88. switch (method) {
  89. case "read":
  90. return resp = pubnub.read(model);
  91. case "create":
  92. return resp = pubnub.create(model);
  93. case "update":
  94. return resp = pubnub.update(model);
  95. case "delete":
  96. return resp = pubnub.destroy(model);
  97. }
  98. } catch (_error) {
  99. error = _error;
  100. errorMessage = error.message;
  101. return console.log("Could not sync: " + errorMessage);
  102. }
  103. };
  104. _sync = Backbone.sync;
  105. Backbone.sync = function(method, model, options) {
  106. var syncMethod;
  107. syncMethod = _sync;
  108. if (model.pubnub || (model.collection && model.collection.pubnub)) {
  109. syncMethod = Backbone.PubNub.sync;
  110. }
  111. return syncMethod.apply(this, [method, model, options]);
  112. };
  113. Backbone.PubNub.Collection = Backbone.Collection.extend({
  114. publish: function(method, model, options) {
  115. var message;
  116. message = {
  117. method: method,
  118. model: model,
  119. options: options,
  120. uuid: this.uuid
  121. };
  122. return this.pubnub.publish({
  123. channel: this.channel,
  124. message: message
  125. });
  126. },
  127. constructor: function(models, options) {
  128. var updateModel,
  129. _this = this;
  130. Backbone.Collection.apply(this, arguments);
  131. if (options && options.pubnub) {
  132. this.pubnub = options.pubnub;
  133. }
  134. this.uuid = this.pubnub.uuid();
  135. this.channel = "backbone-collection-" + this.name;
  136. this.pubnub.subscribe({
  137. channel: this.channel,
  138. callback: function(message) {
  139. _this.off('change', updateModel, _this);
  140. if (message.uuid !== _this.uuid) {
  141. switch (message.method) {
  142. case "create":
  143. _this._onAdded(message.model, message.options);
  144. break;
  145. case "update":
  146. _this._onChanged(message.model, message.options);
  147. break;
  148. case "delete":
  149. _this._onRemoved(message.model, message.options);
  150. }
  151. }
  152. return _this.on('change', updateModel, _this);
  153. }
  154. });
  155. updateModel = function(model) {
  156. return this.publish("update", model);
  157. };
  158. return this.on('change', updateModel, this);
  159. },
  160. _onAdded: function(model, options) {
  161. return Backbone.Collection.prototype.add.apply(this, [model, options]);
  162. },
  163. _onChanged: function(model, options) {
  164. var diff, record;
  165. if (!!model.id) {
  166. record = _.find(this.models, function(record) {
  167. return record.id === model.id;
  168. });
  169. if (record == null) {
  170. console.log("Could not find model with ID: " + model.id);
  171. return false;
  172. }
  173. diff = _.difference(_.keys(record.attributes), _.keys(model));
  174. _.each(diff, function(key) {
  175. return record.unset(key);
  176. });
  177. return record.set(model, options);
  178. }
  179. },
  180. _onRemoved: function(model, options) {
  181. return Backbone.Collection.prototype.remove.apply(this, [model, options]);
  182. },
  183. add: function(models, options) {
  184. var model, _i, _len;
  185. models = _.isArray(models) ? models.slice() : [models];
  186. for (_i = 0, _len = models.length; _i < _len; _i++) {
  187. model = models[_i];
  188. if (model.id == null) {
  189. model.id = this.pubnub.uuid();
  190. }
  191. this.publish("create", model, options);
  192. }
  193. return Backbone.Collection.prototype.add.apply(this, arguments);
  194. },
  195. remove: function(models, options) {
  196. var model, _i, _len;
  197. models = _.isArray(models) ? models.slice() : [models];
  198. for (_i = 0, _len = models.length; _i < _len; _i++) {
  199. model = models[_i];
  200. this.publish("delete", model, options);
  201. }
  202. return Backbone.Collection.prototype.remove.apply(this, arguments);
  203. }
  204. });
  205. Backbone.PubNub.Model = Backbone.Model.extend({
  206. publish: function(method, model, options) {
  207. var message;
  208. message = {
  209. method: method,
  210. model: model,
  211. options: options,
  212. uuid: this.uuid
  213. };
  214. return this.pubnub.publish({
  215. channel: this.channel,
  216. message: message
  217. });
  218. },
  219. constructor: function(model, options) {
  220. var _this = this;
  221. Backbone.Model.apply(this, arguments);
  222. if (options && options.pubnub && options.name) {
  223. this.pubnub = options.pubnub;
  224. this.name = options.name;
  225. }
  226. this.uuid = this.pubnub.uuid();
  227. this.channel = "backbone-model-" + this.name;
  228. this.on('change', this._onChange, this);
  229. return this.pubnub.subscribe({
  230. channel: this.channel,
  231. callback: function(message) {
  232. if (message.uuid !== _this.uuid) {
  233. switch (message.method) {
  234. case "update":
  235. return _this._onChanged(message.model, message.options);
  236. case "delete":
  237. return _this._onRemoved(message.options);
  238. }
  239. }
  240. }
  241. });
  242. },
  243. _onChange: function(model, options) {
  244. return this.publish("update", model, options);
  245. },
  246. _onChanged: function(model, options) {
  247. var diff,
  248. _this = this;
  249. this.off('change', this._onChange, this);
  250. diff = _.difference(_.keys(this.attributes), _.keys(model));
  251. _.each(diff, function(key) {
  252. return _this.unset(key);
  253. });
  254. this.set(model);
  255. return this.on('change', this._onChange, this);
  256. },
  257. _onRemoved: function(options) {
  258. return Backbone.Model.prototype.destroy.apply(this, arguments);
  259. },
  260. destroy: function(options) {
  261. this.publish("delete", null, options);
  262. return Backbone.Model.prototype.destroy.apply(this, arguments);
  263. }
  264. });
  265. }).call(this);