PageRenderTime 27ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/localforage/0.1.0/backbone.localforage.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 256 lines | 187 code | 34 blank | 35 comment | 38 complexity | c2a0bd3d0e3a3e6a6009351eb55a7218 MD5 | raw file
  1. // backbone.localforage allows users of Backbone.js to store their collections
  2. // entirely offline with no communication to a REST server. It uses whatever
  3. // driver localForage is set to use to store the data (IndexedDB, WebSQL, or
  4. // localStorage, depending on availability). This allows apps on Chrome,
  5. // Firefox, IE, and Safari to use async, offline storage, which is cool.
  6. //
  7. // The basics of how to use this library is that it lets you override the
  8. // `sync` method on your collections and models to use localForage. So
  9. //
  10. // var MyModel = Backbone.Collection.extend({})
  11. // var MyCollection = Backbone.Collection.extend({\
  12. // model: MyModel
  13. // });
  14. //
  15. // becomes
  16. //
  17. // var MyModel = Backbone.Collection.extend({
  18. // sync: Backbone.localforage.sync()
  19. // });
  20. // var MyCollection = Backbone.Collection.extend({
  21. // model: MyModel,
  22. // sync: Backbone.localforage.sync('MyCollection')
  23. // });
  24. //
  25. // Inspiration for this file comes from a few backbone.localstorage
  26. // implementations.
  27. (function (root, factory) {
  28. if (typeof define === 'function' && define.amd)
  29. define(['localforage', 'backbone', 'underscore'], factory);
  30. else if (typeof module !== 'undefined' && module.exports) {
  31. var localforage = require('localforage');
  32. var Backbone = require('backbone');
  33. var _ = require('underscore');
  34. module.exports = factory(localforage, Backbone, _);
  35. } else
  36. factory(root.localforage, root.Backbone, root._);
  37. }(this, function (localforage, Backbone, _) {
  38. var Promise = window.Promise;
  39. function S4() {
  40. return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1);
  41. }
  42. function guid() {
  43. return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4();
  44. }
  45. var OfflineStore = function(name) {
  46. // Initialize data as null so we can test to see if it's been loaded
  47. // from our data store later on.
  48. this.data = null;
  49. this.name = name;
  50. };
  51. _.extend(OfflineStore.prototype, {
  52. save: function (callback) {
  53. var _this = this;
  54. return new Promise(function(resolve, reject) {
  55. localforage.setItem(_this.name, JSON.stringify(_this.data), function(data) {
  56. if (callback) {
  57. callback(data);
  58. }
  59. resolve(data);
  60. });
  61. });
  62. },
  63. create: function(model, callbacks) {
  64. var _this = this;
  65. return new Promise(function(resolve, reject) {
  66. if (_this.data) {
  67. if (!model.id) model.id = model.attributes.id = guid();
  68. _this.data[model.id] = model.toJSON();
  69. _this.save(function() {
  70. if (callbacks.success) {
  71. callbacks.success(_this.data[model.id]);
  72. }
  73. resolve(_this.data[model.id]);
  74. });
  75. } else {
  76. localforage.getItem(_this.name, function(data) {
  77. _this.data = JSON.parse(data) || {};
  78. if (!model.id) model.id = model.attributes.id = guid();
  79. _this.data[model.id] = model.toJSON();
  80. _this.save(function() {
  81. if (callbacks.success) {
  82. callbacks.success(_this.data[model.id]);
  83. }
  84. resolve(_this.data[model.id]);
  85. });
  86. });
  87. }
  88. });
  89. },
  90. update: function(model, callbacks) {
  91. var _this = this;
  92. return new Promise(function(resolve, reject) {
  93. if (_this.data) {
  94. _this.data[model.id] = model.toJSON();
  95. _this.save(function() {
  96. if (callbacks.success) {
  97. callbacks.success(_this.data[model.id]);
  98. }
  99. resolve(_this.data[model.id]);
  100. });
  101. } else {
  102. localforage.getItem(_this.name, function(data) {
  103. _this.data = JSON.parse(data) || {};
  104. _this.data[model.id] = model.toJSON();
  105. _this.save(function() {
  106. if (callbacks.success) {
  107. callbacks.success(_this.data[model.id]);
  108. }
  109. resolve(_this.data[model.id]);
  110. });
  111. });
  112. }
  113. });
  114. },
  115. find: function(model, callbacks) {
  116. var _this = this;
  117. return new Promise(function(resolve, reject) {
  118. if (_this.data) {
  119. if (callbacks.success) {
  120. callbacks.success(_this.data[model.id]);
  121. }
  122. resolve(_this.data[model.id]);
  123. } else {
  124. localforage.getItem(_this.name, function(data) {
  125. _this.data = JSON.parse(data) || {};
  126. if (callbacks.success) {
  127. callbacks.success(_this.data[model.id]);
  128. }
  129. resolve(_this.data[model.id]);
  130. });
  131. }
  132. });
  133. },
  134. findAll: function(callbacks) {
  135. var _this = this;
  136. return new Promise(function(resolve, reject) {
  137. if (_this.data) {
  138. if (callbacks.success) {
  139. callbacks.success(_.values(_this.data));
  140. }
  141. resolve(_.values(_this.data));
  142. } else {
  143. localforage.getItem(_this.name, function(data) {
  144. _this.data = JSON.parse(data) || {};
  145. if (callbacks.success) {
  146. callbacks.success(_.values(_this.data));
  147. }
  148. resolve(_.values(_this.data));
  149. });
  150. }
  151. });
  152. },
  153. destroy: function(model, callbacks) {
  154. var _this = this;
  155. return new Promise(function(resolve, reject) {
  156. if (_this.data) {
  157. delete _this.data[model.id];
  158. _this.save(function() {
  159. if (callbacks.success) {
  160. callbacks.success(model);
  161. }
  162. resolve(model);
  163. });
  164. } else {
  165. localforage.getItem(__this.name, function(data) {
  166. _this.data = JSON.parse(data) || {};
  167. delete _this.data[model.id];
  168. _this.save(function() {
  169. if (callbacks.success) {
  170. callbacks.success(model);
  171. }
  172. resolve(model);
  173. });
  174. });
  175. }
  176. });
  177. }
  178. });
  179. function localforageSync(store, method, model, options) {
  180. switch (method) {
  181. case "read":
  182. return model.id ? store.find(model, options) : store.findAll(options);
  183. case "create":
  184. return store.create(model, options);
  185. case "update":
  186. return store.update(model, options);
  187. case "delete":
  188. return store.destroy(model, options);
  189. }
  190. }
  191. // For now, we aren't complicated: just set a property off Backbone to
  192. // serve as our export point.
  193. Backbone.localforage = {
  194. OfflineStore: OfflineStore,
  195. sync: function(name) {
  196. var offlineStore;
  197. var sync;
  198. // If a name's given we create a store for the model or collection;
  199. // otherwise we assume it's a model and try to use its collection's
  200. // store.
  201. if (name) {
  202. offlineStore = new OfflineStore(name);
  203. sync = function(method, model, options) {
  204. return localforageSync.apply(null, [offlineStore].concat([].slice.call(arguments, 0)));
  205. };
  206. sync.offlineStore = offlineStore;
  207. } else {
  208. sync = function(method, model, options) {
  209. var offlineStore = model.collection && model.collection.sync.offlineStore;
  210. if (offlineStore) {
  211. return localforageSync.apply(null, [offlineStore].concat([].slice.call(arguments, 0)));
  212. }
  213. // It relies on Backbone.sync if the model isn't in a collection or
  214. // the collection doesn't have a store
  215. return Backbone.sync.apply(this, arguments);
  216. };
  217. }
  218. return sync;
  219. }
  220. };
  221. return Backbone.localforage;
  222. }));