PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/backbone-localstorage.js/1.1.0/backbone.localStorage.js

https://bitbucket.org/kolbyjAFK/cdnjs
JavaScript | 192 lines | 128 code | 30 blank | 34 comment | 35 complexity | 0d794631f678858cb4787b4d8d6ec4a7 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  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","backbone"], function(_, Backbone) {
  11. // Use global variables if the locals is undefined.
  12. return factory(_ || root._, Backbone || root.Backbone);
  13. });
  14. } else {
  15. // RequireJS isn't being used. Assume underscore and backbone is 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()); this.save();
  62. return this.find(model);
  63. },
  64. // Retrieve a model from `this.data` by id.
  65. find: function(model) {
  66. return this.jsonData(this.localStorage().getItem(this.name+"-"+model.id));
  67. },
  68. // Return the array of all models currently in storage.
  69. findAll: function() {
  70. return _(this.records).chain()
  71. .map(function(id){
  72. return this.jsonData(this.localStorage().getItem(this.name+"-"+id));
  73. }, this)
  74. .compact()
  75. .value();
  76. },
  77. // Delete a model from `this.data`, returning it.
  78. destroy: function(model) {
  79. if (model.isNew())
  80. return false
  81. this.localStorage().removeItem(this.name+"-"+model.id);
  82. this.records = _.reject(this.records, function(id){
  83. return id === model.id.toString();
  84. });
  85. this.save();
  86. return model;
  87. },
  88. localStorage: function() {
  89. return localStorage;
  90. },
  91. // fix for "illegal access" error on Android when JSON.parse is passed null
  92. jsonData: function (data) {
  93. return data && JSON.parse(data);
  94. }
  95. });
  96. // localSync delegate to the model or collection's
  97. // *localStorage* property, which should be an instance of `Store`.
  98. // window.Store.sync and Backbone.localSync is deprectated, use Backbone.LocalStorage.sync instead
  99. Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(method, model, options) {
  100. var store = model.localStorage || model.collection.localStorage;
  101. var resp, errorMessage, syncDfd = $.Deferred && $.Deferred(); //If $ is having Deferred - use it.
  102. try {
  103. switch (method) {
  104. case "read":
  105. resp = model.id != undefined ? store.find(model) : store.findAll();
  106. break;
  107. case "create":
  108. resp = store.create(model);
  109. break;
  110. case "update":
  111. resp = store.update(model);
  112. break;
  113. case "delete":
  114. resp = store.destroy(model);
  115. break;
  116. }
  117. } catch(error) {
  118. if (error.code === DOMException.QUOTA_EXCEEDED_ERR && window.localStorage.length === 0)
  119. errorMessage = "Private browsing is unsupported";
  120. else
  121. errorMessage = error.message;
  122. }
  123. if (resp) {
  124. if (options && options.success)
  125. if (Backbone.VERSION === "0.9.10") {
  126. options.success(model, resp, options);
  127. } else {
  128. options.success(resp);
  129. }
  130. if (syncDfd)
  131. syncDfd.resolve(resp);
  132. } else {
  133. errorMessage = errorMessage ? errorMessage
  134. : "Record Not Found";
  135. if (options && options.error)
  136. if (Backbone.VERSION === "0.9.10") {
  137. options.error(model, errorMessage, options);
  138. } else {
  139. options.error(errorMessage);
  140. }
  141. if (syncDfd)
  142. syncDfd.reject(errorMessage);
  143. }
  144. // add compatibility with $.ajax
  145. // always execute callback for success and error
  146. if (options && options.complete) options.complete(resp);
  147. return syncDfd && syncDfd.promise();
  148. };
  149. Backbone.ajaxSync = Backbone.sync;
  150. Backbone.getSyncMethod = function(model) {
  151. if(model.localStorage || (model.collection && model.collection.localStorage)) {
  152. return Backbone.localSync;
  153. }
  154. return Backbone.ajaxSync;
  155. };
  156. // Override 'Backbone.sync' to default to localSync,
  157. // the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
  158. Backbone.sync = function(method, model, options) {
  159. return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
  160. };
  161. return Backbone.LocalStorage;
  162. }));