<!DOCTYPE html>

<html>
<head>
  <title>backbone.localstorage.js</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page">
            
              
              <a class="source" href="backbone.localstorage.html">
                backbone.localstorage.js
              </a>
            
              
              <a class="source" href="todos.html">
                todos.js
              </a>
            
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>backbone.localstorage.js</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre><span class="comment">/**
 * Backbone localStorage Adapter
 * Version 1.1.0
 *
 * https://github.com/jeromegn/Backbone.localStorage
 */</span>
(<span class="function"><span class="keyword">function</span> <span class="params">(root, factory)</span> {</span>
   <span class="keyword">if</span> (<span class="keyword">typeof</span> define === <span class="string">"function"</span> &amp;&amp; define.amd) {</pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>AMD. Register as an anonymous module.</p>

            </div>
            
            <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>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>Use global variables if the locals are undefined.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">return</span> factory(_ || root._, Backbone || root.Backbone);
      });
   } <span class="keyword">else</span> {</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>RequireJS isn&#39;t being used. Assume underscore and backbone are loaded in <script> tags</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      factory(_, Backbone);
   }
}(<span class="keyword">this</span>, <span class="keyword">function</span>(_, Backbone) {</pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <p>A simple module to replace <code>Backbone.sync</code> with <em>localStorage</em>-based
persistence. Models are given GUIDS, and saved into a JSON object. Simple
as that.</p>
<p>Hold reference to Underscore.js and Backbone.js in the closure in order
to make things work even if they are removed from the global namespace</p>
<p>Generate four random hex digits.</p>

            </div>
            
            <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>
   <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>);
};</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>Generate a pseudo-GUID by concatenating random hexadecimal.</p>

            </div>
            
            <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>
   <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());
};</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <p>Our Store is represented by a single JS object in <em>localStorage</em>. Create it
with a meaningful name, like the name you&#39;d give a table.
window.Store is deprectated, use Backbone.LocalStorage instead</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Backbone.LocalStorage = window.Store = <span class="keyword">function</span>(name) {
  <span class="keyword">this</span>.name = name;
  <span class="keyword">var</span> store = <span class="keyword">this</span>.localStorage().getItem(<span class="keyword">this</span>.name);
  <span class="keyword">this</span>.records = (store &amp;&amp; store.split(<span class="string">","</span>)) || [];
};

_.extend(Backbone.LocalStorage.prototype, {</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>Save the current state of the <strong>Store</strong> to <em>localStorage</em>.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  save: <span class="keyword">function</span>() {
    <span class="keyword">this</span>.localStorage().setItem(<span class="keyword">this</span>.name, <span class="keyword">this</span>.records.join(<span class="string">","</span>));
  },</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>Add a model, giving it a (hopefully)-unique GUID, if it doesn&#39;t already
have an id of it&#39;s own.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  create: <span class="keyword">function</span>(model) {
    <span class="keyword">if</span> (!model.id) {
      model.id = guid();
      model.set(model.idAttribute, model.id);
    }
    <span class="keyword">this</span>.localStorage().setItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id, JSON.stringify(model));
    <span class="keyword">this</span>.records.push(model.id.toString());
    <span class="keyword">this</span>.save();
    <span class="keyword">return</span> <span class="keyword">this</span>.find(model);
  },</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>Update a model by replacing its copy in <code>this.data</code>.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  update: <span class="keyword">function</span>(model) {
    <span class="keyword">this</span>.localStorage().setItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id, JSON.stringify(model));
    <span class="keyword">if</span> (!_.include(<span class="keyword">this</span>.records, model.id.toString()))
      <span class="keyword">this</span>.records.push(model.id.toString()); <span class="keyword">this</span>.save();
    <span class="keyword">return</span> <span class="keyword">this</span>.find(model);
  },</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <p>Retrieve a model from <code>this.data</code> by id.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  find: <span class="keyword">function</span>(model) {
    <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));
  },</pre></div></div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              <p>Return the array of all models currently in storage.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  findAll: <span class="keyword">function</span>() {
    <span class="keyword">return</span> _(<span class="keyword">this</span>.records).chain()
      .map(<span class="keyword">function</span>(id){
        <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));
      }, <span class="keyword">this</span>)
      .compact()
      .value();
  },</pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <p>Delete a model from <code>this.data</code>, returning it.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  destroy: <span class="keyword">function</span>(model) {
    <span class="keyword">if</span> (model.isNew())
      <span class="keyword">return</span> <span class="literal">false</span>
    <span class="keyword">this</span>.localStorage().removeItem(<span class="keyword">this</span>.name+<span class="string">"-"</span>+model.id);
    <span class="keyword">this</span>.records = _.reject(<span class="keyword">this</span>.records, <span class="keyword">function</span>(id){
      <span class="keyword">return</span> id === model.id.toString();
    });
    <span class="keyword">this</span>.save();
    <span class="keyword">return</span> model;
  },

  localStorage: <span class="keyword">function</span>() {
    <span class="keyword">return</span> localStorage;
  },</pre></div></div>
            
        </li>
        
        
        <li id="section-14">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-14">&#182;</a>
              </div>
              <p>fix for &quot;illegal access&quot; error on Android when JSON.parse is passed null</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  jsonData: <span class="function"><span class="keyword">function</span> <span class="params">(data)</span> {</span>
      <span class="keyword">return</span> data &amp;&amp; JSON.parse(data);
  }

});</pre></div></div>
            
        </li>
        
        
        <li id="section-15">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-15">&#182;</a>
              </div>
              <p>localSync delegate to the model or collection&#39;s
<em>localStorage</em> property, which should be an instance of <code>Store</code>.
window.Store.sync and Backbone.localSync is deprectated, use Backbone.LocalStorage.sync instead</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = <span class="keyword">function</span>(method, model, options) {
  <span class="keyword">var</span> store = model.localStorage || model.collection.localStorage;

  <span class="keyword">var</span> resp, errorMessage, syncDfd = $.Deferred &amp;&amp; $.Deferred(); <span class="comment">//If $ is having Deferred - use it.</span>

  <span class="keyword">try</span> {

    <span class="keyword">switch</span> (method) {
      <span class="keyword">case</span> <span class="string">"read"</span>:
        resp = model.id != <span class="literal">undefined</span> ? store.find(model) : store.findAll();
        <span class="keyword">break</span>;
      <span class="keyword">case</span> <span class="string">"create"</span>:
        resp = store.create(model);
        <span class="keyword">break</span>;
      <span class="keyword">case</span> <span class="string">"update"</span>:
        resp = store.update(model);
        <span class="keyword">break</span>;
      <span class="keyword">case</span> <span class="string">"delete"</span>:
        resp = store.destroy(model);
        <span class="keyword">break</span>;
    }

  } <span class="keyword">catch</span>(error) {
    <span class="keyword">if</span> (error.code === DOMException.QUOTA_EXCEEDED_ERR &amp;&amp; window.localStorage.length === <span class="number">0</span>)
      errorMessage = <span class="string">"Private browsing is unsupported"</span>;
    <span class="keyword">else</span>
      errorMessage = error.message;
  }

  <span class="keyword">if</span> (resp) {
    model.trigger(<span class="string">"sync"</span>, model, resp, options);
    <span class="keyword">if</span> (options &amp;&amp; options.success)
      options.success(resp);
    <span class="keyword">if</span> (syncDfd)
      syncDfd.resolve(resp);

  } <span class="keyword">else</span> {
    errorMessage = errorMessage ? errorMessage
                                : <span class="string">"Record Not Found"</span>;

    <span class="keyword">if</span> (options &amp;&amp; options.error)
      options.error(errorMessage);
    <span class="keyword">if</span> (syncDfd)
      syncDfd.reject(errorMessage);
  }</pre></div></div>
            
        </li>
        
        
        <li id="section-16">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-16">&#182;</a>
              </div>
              <p>add compatibility with $.ajax
always execute callback for success and error</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  <span class="keyword">if</span> (options &amp;&amp; options.complete) options.complete(resp);

  <span class="keyword">return</span> syncDfd &amp;&amp; syncDfd.promise();
};

Backbone.ajaxSync = Backbone.sync;

Backbone.getSyncMethod = <span class="keyword">function</span>(model) {
  <span class="keyword">if</span>(model.localStorage || (model.collection &amp;&amp; model.collection.localStorage)) {
    <span class="keyword">return</span> Backbone.localSync;
  }

  <span class="keyword">return</span> Backbone.ajaxSync;
};</pre></div></div>
            
        </li>
        
        
        <li id="section-17">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-17">&#182;</a>
              </div>
              <p>Override &#39;Backbone.sync&#39; to default to localSync,
the original &#39;Backbone.sync&#39; is still available in &#39;Backbone.ajaxSync&#39;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Backbone.sync = <span class="keyword">function</span>(method, model, options) {
  <span class="keyword">return</span> Backbone.getSyncMethod(model).apply(<span class="keyword">this</span>, [method, model, options]);
};

<span class="keyword">return</span> Backbone.LocalStorage;
}));</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>