PageRenderTime 28ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/backbone.localstorage.html

https://github.com/huangbaihua001/backbone
HTML | 458 lines | 328 code | 130 blank | 0 comment | 0 complexity | d08f053b0082735e34bcec5e84cd09fc MD5 | raw file
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>backbone.localstorage.js</title>
  5. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  6. <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  7. <link rel="stylesheet" media="all" href="docco.css" />
  8. </head>
  9. <body>
  10. <div id="container">
  11. <div id="background"></div>
  12. <ul id="jump_to">
  13. <li>
  14. <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
  15. <a class="small" href="javascript:void(0);">+</a>
  16. <div id="jump_wrapper">
  17. <div id="jump_page">
  18. <a class="source" href="backbone.localstorage.html">
  19. backbone.localstorage.js
  20. </a>
  21. <a class="source" href="todos.html">
  22. todos.js
  23. </a>
  24. </div>
  25. </li>
  26. </ul>
  27. <ul class="sections">
  28. <li id="title">
  29. <div class="annotation">
  30. <h1>backbone.localstorage.js</h1>
  31. </div>
  32. </li>
  33. <li id="section-1">
  34. <div class="annotation">
  35. <div class="pilwrap ">
  36. <a class="pilcrow" href="#section-1">&#182;</a>
  37. </div>
  38. </div>
  39. <div class="content"><div class='highlight'><pre><span class="comment">/**
  40. * Backbone localStorage Adapter
  41. * Version 1.1.0
  42. *
  43. * https://github.com/jeromegn/Backbone.localStorage
  44. */</span>
  45. (<span class="function"><span class="keyword">function</span> <span class="params">(root, factory)</span> {</span>
  46. <span class="keyword">if</span> (<span class="keyword">typeof</span> define === <span class="string">"function"</span> &amp;&amp; define.amd) {</pre></div></div>
  47. </li>
  48. <li id="section-2">
  49. <div class="annotation">
  50. <div class="pilwrap ">
  51. <a class="pilcrow" href="#section-2">&#182;</a>
  52. </div>
  53. <p>AMD. Register as an anonymous module.
  54. </p>
  55. </div>
  56. <div class="content"><div class='highlight'><pre> define([<span class="string">"underscore"</span>,<span class="string">"backbone"</span>], <span class="keyword">function</span>(_, Backbone) {</pre></div></div>
  57. </li>
  58. <li id="section-3">
  59. <div class="annotation">
  60. <div class="pilwrap ">
  61. <a class="pilcrow" href="#section-3">&#182;</a>
  62. </div>
  63. <p>Use global variables if the locals are undefined.
  64. </p>
  65. </div>
  66. <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> factory(_ || root._, Backbone || root.Backbone);
  67. });
  68. } <span class="keyword">else</span> {</pre></div></div>
  69. </li>
  70. <li id="section-4">
  71. <div class="annotation">
  72. <div class="pilwrap ">
  73. <a class="pilcrow" href="#section-4">&#182;</a>
  74. </div>
  75. <p>RequireJS isn&#39;t being used. Assume underscore and backbone are loaded in <script> tags
  76. </p>
  77. </div>
  78. <div class="content"><div class='highlight'><pre> factory(_, Backbone);
  79. }
  80. }(<span class="keyword">this</span>, <span class="keyword">function</span>(_, Backbone) {</pre></div></div>
  81. </li>
  82. <li id="section-5">
  83. <div class="annotation">
  84. <div class="pilwrap ">
  85. <a class="pilcrow" href="#section-5">&#182;</a>
  86. </div>
  87. <p>A simple module to replace <code>Backbone.sync</code> with <em>localStorage</em>-based
  88. persistence. Models are given GUIDS, and saved into a JSON object. Simple
  89. as that.
  90. </p>
  91. <p>Hold reference to Underscore.js and Backbone.js in the closure in order
  92. to make things work even if they are removed from the global namespace
  93. </p>
  94. <p>Generate four random hex digits.
  95. </p>
  96. </div>
  97. <div class="content"><div class='highlight'><pre><span class="function"><span class="keyword">function</span> <span class="title">S4</span><span class="params">()</span> {</span>
  98. <span class="keyword">return</span> (((<span class="number">1</span>+Math.random())*<span class="number">0x10000</span>)|<span class="number">0</span>).toString(<span class="number">16</span>).substring(<span class="number">1</span>);
  99. };</pre></div></div>
  100. </li>
  101. <li id="section-6">
  102. <div class="annotation">
  103. <div class="pilwrap ">
  104. <a class="pilcrow" href="#section-6">&#182;</a>
  105. </div>
  106. <p>Generate a pseudo-GUID by concatenating random hexadecimal.
  107. </p>
  108. </div>
  109. <div class="content"><div class='highlight'><pre><span class="function"><span class="keyword">function</span> <span class="title">guid</span><span class="params">()</span> {</span>
  110. <span class="keyword">return</span> (S4()+S4()+<span class="string">"-"</span>+S4()+<span class="string">"-"</span>+S4()+<span class="string">"-"</span>+S4()+<span class="string">"-"</span>+S4()+S4()+S4());
  111. };</pre></div></div>
  112. </li>
  113. <li id="section-7">
  114. <div class="annotation">
  115. <div class="pilwrap ">
  116. <a class="pilcrow" href="#section-7">&#182;</a>
  117. </div>
  118. <p>Our Store is represented by a single JS object in <em>localStorage</em>. Create it
  119. with a meaningful name, like the name you&#39;d give a table.
  120. window.Store is deprectated, use Backbone.LocalStorage instead
  121. </p>
  122. </div>
  123. <div class="content"><div class='highlight'><pre>Backbone.LocalStorage = window.Store = <span class="keyword">function</span>(name) {
  124. <span class="keyword">this</span>.name = name;
  125. <span class="keyword">var</span> store = <span class="keyword">this</span>.localStorage().getItem(<span class="keyword">this</span>.name);
  126. <span class="keyword">this</span>.records = (store &amp;&amp; store.split(<span class="string">","</span>)) || [];
  127. };
  128. _.extend(Backbone.LocalStorage.prototype, {</pre></div></div>
  129. </li>
  130. <li id="section-8">
  131. <div class="annotation">
  132. <div class="pilwrap ">
  133. <a class="pilcrow" href="#section-8">&#182;</a>
  134. </div>
  135. <p>Save the current state of the <strong>Store</strong> to <em>localStorage</em>.
  136. </p>
  137. </div>
  138. <div class="content"><div class='highlight'><pre> save: <span class="keyword">function</span>() {
  139. <span class="keyword">this</span>.localStorage().setItem(<span class="keyword">this</span>.name, <span class="keyword">this</span>.records.join(<span class="string">","</span>));
  140. },</pre></div></div>
  141. </li>
  142. <li id="section-9">
  143. <div class="annotation">
  144. <div class="pilwrap ">
  145. <a class="pilcrow" href="#section-9">&#182;</a>
  146. </div>
  147. <p>Add a model, giving it a (hopefully)-unique GUID, if it doesn&#39;t already
  148. have an id of it&#39;s own.
  149. </p>
  150. </div>
  151. <div class="content"><div class='highlight'><pre> create: <span class="keyword">function</span>(model) {
  152. <span class="keyword">if</span> (!model.id) {
  153. model.id = guid();
  154. model.set(model.idAttribute, model.id);
  155. }
  156. <span class="keyword">this</span>.localStorage().setItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id, JSON.stringify(model));
  157. <span class="keyword">this</span>.records.push(model.id.toString());
  158. <span class="keyword">this</span>.save();
  159. <span class="keyword">return</span> <span class="keyword">this</span>.find(model);
  160. },</pre></div></div>
  161. </li>
  162. <li id="section-10">
  163. <div class="annotation">
  164. <div class="pilwrap ">
  165. <a class="pilcrow" href="#section-10">&#182;</a>
  166. </div>
  167. <p>Update a model by replacing its copy in <code>this.data</code>.
  168. </p>
  169. </div>
  170. <div class="content"><div class='highlight'><pre> update: <span class="keyword">function</span>(model) {
  171. <span class="keyword">this</span>.localStorage().setItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id, JSON.stringify(model));
  172. <span class="keyword">if</span> (!_.include(<span class="keyword">this</span>.records, model.id.toString()))
  173. <span class="keyword">this</span>.records.push(model.id.toString()); <span class="keyword">this</span>.save();
  174. <span class="keyword">return</span> <span class="keyword">this</span>.find(model);
  175. },</pre></div></div>
  176. </li>
  177. <li id="section-11">
  178. <div class="annotation">
  179. <div class="pilwrap ">
  180. <a class="pilcrow" href="#section-11">&#182;</a>
  181. </div>
  182. <p>Retrieve a model from <code>this.data</code> by id.
  183. </p>
  184. </div>
  185. <div class="content"><div class='highlight'><pre> find: <span class="keyword">function</span>(model) {
  186. <span class="keyword">return</span> <span class="keyword">this</span>.jsonData(<span class="keyword">this</span>.localStorage().getItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id));
  187. },</pre></div></div>
  188. </li>
  189. <li id="section-12">
  190. <div class="annotation">
  191. <div class="pilwrap ">
  192. <a class="pilcrow" href="#section-12">&#182;</a>
  193. </div>
  194. <p>Return the array of all models currently in storage.
  195. </p>
  196. </div>
  197. <div class="content"><div class='highlight'><pre> findAll: <span class="keyword">function</span>() {
  198. <span class="keyword">return</span> _(<span class="keyword">this</span>.records).chain()
  199. .map(<span class="keyword">function</span>(id){
  200. <span class="keyword">return</span> <span class="keyword">this</span>.jsonData(<span class="keyword">this</span>.localStorage().getItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+id));
  201. }, <span class="keyword">this</span>)
  202. .compact()
  203. .value();
  204. },</pre></div></div>
  205. </li>
  206. <li id="section-13">
  207. <div class="annotation">
  208. <div class="pilwrap ">
  209. <a class="pilcrow" href="#section-13">&#182;</a>
  210. </div>
  211. <p>Delete a model from <code>this.data</code>, returning it.
  212. </p>
  213. </div>
  214. <div class="content"><div class='highlight'><pre> destroy: <span class="keyword">function</span>(model) {
  215. <span class="keyword">if</span> (model.isNew())
  216. <span class="keyword">return</span> <span class="literal">false</span>
  217. <span class="keyword">this</span>.localStorage().removeItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id);
  218. <span class="keyword">this</span>.records = _.reject(<span class="keyword">this</span>.records, <span class="keyword">function</span>(id){
  219. <span class="keyword">return</span> id === model.id.toString();
  220. });
  221. <span class="keyword">this</span>.save();
  222. <span class="keyword">return</span> model;
  223. },
  224. localStorage: <span class="keyword">function</span>() {
  225. <span class="keyword">return</span> localStorage;
  226. },</pre></div></div>
  227. </li>
  228. <li id="section-14">
  229. <div class="annotation">
  230. <div class="pilwrap ">
  231. <a class="pilcrow" href="#section-14">&#182;</a>
  232. </div>
  233. <p>fix for &quot;illegal access&quot; error on Android when JSON.parse is passed null
  234. </p>
  235. </div>
  236. <div class="content"><div class='highlight'><pre> jsonData: <span class="function"><span class="keyword">function</span> <span class="params">(data)</span> {</span>
  237. <span class="keyword">return</span> data &amp;&amp; JSON.parse(data);
  238. }
  239. });</pre></div></div>
  240. </li>
  241. <li id="section-15">
  242. <div class="annotation">
  243. <div class="pilwrap ">
  244. <a class="pilcrow" href="#section-15">&#182;</a>
  245. </div>
  246. <p>localSync delegate to the model or collection&#39;s
  247. <em>localStorage</em> property, which should be an instance of <code>Store</code>.
  248. window.Store.sync and Backbone.localSync is deprectated, use Backbone.LocalStorage.sync instead
  249. </p>
  250. </div>
  251. <div class="content"><div class='highlight'><pre>Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = <span class="keyword">function</span>(method, model, options) {
  252. <span class="keyword">var</span> store = model.localStorage || model.collection.localStorage;
  253. <span class="keyword">var</span> resp, errorMessage, syncDfd = $.Deferred &amp;&amp; $.Deferred(); <span class="comment">//If $ is having Deferred - use it.</span>
  254. <span class="keyword">try</span> {
  255. <span class="keyword">switch</span> (method) {
  256. <span class="keyword">case</span> <span class="string">"read"</span>:
  257. resp = model.id != <span class="literal">undefined</span> ? store.find(model) : store.findAll();
  258. <span class="keyword">break</span>;
  259. <span class="keyword">case</span> <span class="string">"create"</span>:
  260. resp = store.create(model);
  261. <span class="keyword">break</span>;
  262. <span class="keyword">case</span> <span class="string">"update"</span>:
  263. resp = store.update(model);
  264. <span class="keyword">break</span>;
  265. <span class="keyword">case</span> <span class="string">"delete"</span>:
  266. resp = store.destroy(model);
  267. <span class="keyword">break</span>;
  268. }
  269. } <span class="keyword">catch</span>(error) {
  270. <span class="keyword">if</span> (error.code === DOMException.QUOTA_EXCEEDED_ERR &amp;&amp; window.localStorage.length === <span class="number">0</span>)
  271. errorMessage = <span class="string">"Private browsing is unsupported"</span>;
  272. <span class="keyword">else</span>
  273. errorMessage = error.message;
  274. }
  275. <span class="keyword">if</span> (resp) {
  276. model.trigger(<span class="string">"sync"</span>, model, resp, options);
  277. <span class="keyword">if</span> (options &amp;&amp; options.success)
  278. options.success(resp);
  279. <span class="keyword">if</span> (syncDfd)
  280. syncDfd.resolve(resp);
  281. } <span class="keyword">else</span> {
  282. errorMessage = errorMessage ? errorMessage
  283. : <span class="string">"Record Not Found"</span>;
  284. <span class="keyword">if</span> (options &amp;&amp; options.error)
  285. options.error(errorMessage);
  286. <span class="keyword">if</span> (syncDfd)
  287. syncDfd.reject(errorMessage);
  288. }</pre></div></div>
  289. </li>
  290. <li id="section-16">
  291. <div class="annotation">
  292. <div class="pilwrap ">
  293. <a class="pilcrow" href="#section-16">&#182;</a>
  294. </div>
  295. <p>add compatibility with $.ajax
  296. always execute callback for success and error
  297. </p>
  298. </div>
  299. <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (options &amp;&amp; options.complete) options.complete(resp);
  300. <span class="keyword">return</span> syncDfd &amp;&amp; syncDfd.promise();
  301. };
  302. Backbone.ajaxSync = Backbone.sync;
  303. Backbone.getSyncMethod = <span class="keyword">function</span>(model) {
  304. <span class="keyword">if</span>(model.localStorage || (model.collection &amp;&amp; model.collection.localStorage)) {
  305. <span class="keyword">return</span> Backbone.localSync;
  306. }
  307. <span class="keyword">return</span> Backbone.ajaxSync;
  308. };</pre></div></div>
  309. </li>
  310. <li id="section-17">
  311. <div class="annotation">
  312. <div class="pilwrap ">
  313. <a class="pilcrow" href="#section-17">&#182;</a>
  314. </div>
  315. <p>Override &#39;Backbone.sync&#39; to default to localSync,
  316. the original &#39;Backbone.sync&#39; is still available in &#39;Backbone.ajaxSync&#39;
  317. </p>
  318. </div>
  319. <div class="content"><div class='highlight'><pre>Backbone.sync = <span class="keyword">function</span>(method, model, options) {
  320. <span class="keyword">return</span> Backbone.getSyncMethod(model).apply(<span class="keyword">this</span>, [method, model, options]);
  321. };
  322. <span class="keyword">return</span> Backbone.LocalStorage;
  323. }));</pre></div></div>
  324. </li>
  325. </ul>
  326. </div>
  327. </body>
  328. </html>