PageRenderTime 49ms CodeModel.GetById 3ms RepoModel.GetById 0ms app.codeStats 0ms

/web-app/lib/backbone/backbone.localStorage.js

https://github.com/delfianto/rams-web-app
JavaScript | 195 lines | 131 code | 30 blank | 34 comment | 35 complexity | afb5c252b1015b55493e95d0bde38f97 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. /**
  2. * Backbone localStorage Adapter
  3. * Version 1.1.0
  4. *
  5. * https://github.com/jeromegn/Backbone.localStorage
  6. */
  7. (function (root, factory) {
  8. if (typeof define === "function" && define.amd) {
  9. // AMD. Register as an anonymous module.
  10. define(["../underscore/underscore", "backbone"], function (_, Backbone) {
  11. // Use global variables if the locals are undefined.
  12. return factory(_ || root._, Backbone || root.Backbone);
  13. });
  14. } else {
  15. // RequireJS isn't being used. Assume underscore and backbone are loaded in <script> tags
  16. factory(_, Backbone);
  17. }
  18. }(this, function (_, Backbone) {
  19. // A simple module to replace `Backbone.sync` with *localStorage*-based
  20. // persistence. Models are given GUIDS, and saved into a JSON object. Simple
  21. // as that.
  22. // Hold reference to Underscore.js and Backbone.js in the closure in order
  23. // to make things work even if they are removed from the global namespace
  24. // Generate four random hex digits.
  25. function S4() {
  26. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  27. };
  28. // Generate a pseudo-GUID by concatenating random hexadecimal.
  29. function guid() {
  30. return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  31. };
  32. // Our Store is represented by a single JS object in *localStorage*. Create it
  33. // with a meaningful name, like the name you'd give a table.
  34. // window.Store is deprectated, use Backbone.LocalStorage instead
  35. Backbone.LocalStorage = window.Store = function (name) {
  36. this.name = name;
  37. var store = this.localStorage().getItem(this.name);
  38. this.records = (store && store.split(",")) || [];
  39. };
  40. _.extend(Backbone.LocalStorage.prototype, {
  41. // Save the current state of the **Store** to *localStorage*.
  42. save: function () {
  43. this.localStorage().setItem(this.name, this.records.join(","));
  44. },
  45. // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
  46. // have an id of it's own.
  47. create: function (model) {
  48. if (!model.id) {
  49. model.id = guid();
  50. model.set(model.idAttribute, model.id);
  51. }
  52. this.localStorage().setItem(this.name + "-" + model.id, JSON.stringify(model));
  53. this.records.push(model.id.toString());
  54. this.save();
  55. return this.find(model);
  56. },
  57. // Update a model by replacing its copy in `this.data`.
  58. update: function (model) {
  59. this.localStorage().setItem(this.name + "-" + model.id, JSON.stringify(model));
  60. if (!_.include(this.records, model.id.toString()))
  61. this.records.push(model.id.toString());
  62. this.save();
  63. return this.find(model);
  64. },
  65. // Retrieve a model from `this.data` by id.
  66. find: function (model) {
  67. return this.jsonData(this.localStorage().getItem(this.name + "-" + model.id));
  68. },
  69. // Return the array of all models currently in storage.
  70. findAll: function () {
  71. return _(this.records).chain()
  72. .map(function (id) {
  73. return this.jsonData(this.localStorage().getItem(this.name + "-" + id));
  74. }, this)
  75. .compact()
  76. .value();
  77. },
  78. // Delete a model from `this.data`, returning it.
  79. destroy: function (model) {
  80. if (model.isNew())
  81. return false
  82. this.localStorage().removeItem(this.name + "-" + model.id);
  83. this.records = _.reject(this.records, function (id) {
  84. return id === model.id.toString();
  85. });
  86. this.save();
  87. return model;
  88. },
  89. localStorage: function () {
  90. return localStorage;
  91. },
  92. // fix for "illegal access" error on Android when JSON.parse is passed null
  93. jsonData: function (data) {
  94. return data && JSON.parse(data);
  95. }
  96. });
  97. // localSync delegate to the model or collection's
  98. // *localStorage* property, which should be an instance of `Store`.
  99. // window.Store.sync and Backbone.localSync is deprectated, use Backbone.LocalStorage.sync instead
  100. Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function (method, model, options) {
  101. var store = model.localStorage || model.collection.localStorage;
  102. var resp, errorMessage, syncDfd = $.Deferred && $.Deferred(); //If $ is having Deferred - use it.
  103. try {
  104. switch (method) {
  105. case "read":
  106. resp = model.id != undefined ? store.find(model) : store.findAll();
  107. break;
  108. case "create":
  109. resp = store.create(model);
  110. break;
  111. case "update":
  112. resp = store.update(model);
  113. break;
  114. case "delete":
  115. resp = store.destroy(model);
  116. break;
  117. }
  118. } catch (error) {
  119. if (error.code === DOMException.QUOTA_EXCEEDED_ERR && window.localStorage.length === 0)
  120. errorMessage = "Private browsing is unsupported";
  121. else
  122. errorMessage = error.message;
  123. }
  124. if (resp) {
  125. model.trigger("sync", model, resp, options);
  126. if (options && options.success)
  127. if (Backbone.VERSION === "0.9.10") {
  128. options.success(model, resp, options);
  129. } else {
  130. options.success(resp);
  131. }
  132. if (syncDfd)
  133. syncDfd.resolve(resp);
  134. } else {
  135. errorMessage = errorMessage ? errorMessage
  136. : "Record Not Found";
  137. model.trigger("error", model, errorMessage, options);
  138. if (options && options.error)
  139. if (Backbone.VERSION === "0.9.10") {
  140. options.error(model, errorMessage, options);
  141. } else {
  142. options.error(errorMessage);
  143. }
  144. if (syncDfd)
  145. syncDfd.reject(errorMessage);
  146. }
  147. // add compatibility with $.ajax
  148. // always execute callback for success and error
  149. if (options && options.complete) options.complete(resp);
  150. return syncDfd && syncDfd.promise();
  151. };
  152. Backbone.ajaxSync = Backbone.sync;
  153. Backbone.getSyncMethod = function (model) {
  154. if (model.localStorage || (model.collection && model.collection.localStorage)) {
  155. return Backbone.localSync;
  156. }
  157. return Backbone.ajaxSync;
  158. };
  159. // Override 'Backbone.sync' to default to localSync,
  160. // the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
  161. Backbone.sync = function (method, model, options) {
  162. return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
  163. };
  164. return Backbone.LocalStorage;
  165. }));