Saving Objects to Web Storage Using JSON
Saving Objects to Web Storage Using JSON
We will now investigate saving JavaScript objects to Web Storage using JSON. JSON provides an elegant and efficient method of storing JavaScript object data as a plain text string. Once in string format, the data can then be sent to external services or saved as
50 CHAPTER 3: HTML5 Storage APIs
per the samples here. Before you begin saving objects in JSON format, however, you are going to need Douglas Crockford’s json2.js library for serializing/deserializing objects to JSON strings. This library is available at the following location: http://json.org/json2.js.
You can download that file into your top-level js directory so you can use it for other exercises later on.
NOTE: Doug Crockford has included an alert in the first line of the json2.js file to discourage people from using the library via a direct link to his site. You will need to remove this line before running code samples from the exercise. If you forget, though, everything will work; you’ll just have to click through an annoying alert each time you run an exercise using JSON. We’re fairly confident that by the end of the book that first line will be removed.
Let’s create a simple page that will set up the environment for us to run our tests: <html>
<head> <title>Web Storage Tester</title> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-
scale=1.0; user-scalable=0;" />
<link rel="stylesheet" media="screen" href="../../css/snippets.css" />
<script type="text/javascript" src="../../js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../js/json2.js"></script> <script type="text/javascript" src="../../js/prowebapps.js"></script> <script type="text/javascript" src="webstorage-test.js"></script>
</head> <body>
<h1 class="fancy">Web Storage JSON Wrapper</h1> <ul id="items">
<li class="header">Items in Storage (tap to remove)</li> </ul> <ul id="newitem">
<li class="header">New Item</li> <li class="bordered"><input type="text" id="newtitle" placeholder="Title"
/></li> </ul> <ul id="actions">
<li><button id="add">Add</button></li> <li><button id="clear">Clear</button></li>
</ul> </body> <html>
In the preceding code, there are four general items to take note of:
Inclusion of the generic snippets stylesheet (css/snippets.css). As outlined in Chapter 1, this stylesheet forms part of the reusable code components that we will use and expand on over the course of the book. Full source of the stylesheet is viewable at the following URL: http://sidelab.com/code/pawa/css/snippets.css.
CHAPTER 3: HTML5 Storage APIs
Inclusion of json2.js so we can access JSON serialization and parsing.
Inclusion of the prowebapps.js library. We will add some handy wrappers for saving to localStorage/sessionStorage, which will provide automatic serialization/deserialization of objects using JSON.
Inclusion of webstorage-test.js, which will include the JavaScript code for this exercise.
Let’s get on with coding. First, we’ll add those storage wrapper functions to the prowebapps.js library. This is done by adding a Storage submodule to our existing PROWEBAPPS module:
var module = { Storage: (function() { function getStorageScope(scope) { if (scope && (scope == "session")) { return sessionStorage; } // if
return localStorage; } // getStorageTarget
return { get: function(key, scope) { // get the storage target var value = getStorageScope(scope).getItem(key);
// if the value looks like serialized JSON, parse it return (/^(\{|\[).*(\}|\])$/).test(value) ? JSON.parse(value) : value;
set: function(key, value, scope) { // if the value is an object, then stringify using JSON var serializable = jQuery.isArray(value) || jQuery.isPlainObject(value); var storeValue = serializable ? JSON.stringify(value) : value;
// save the value getStorageScope(scope).setItem(key, storeValue);
remove: function(key, scope) { getStorageScope(scope).removeItem(key); } }; })()
While we won’t go into a detailed explanation of the preceding code, those of you who are interested will be able to see that we wrap the getItem and setItem methods of the HTML5 Storage interface into get and set static methods on the PROWEBAPPS.Storage module. We use some jQuery utility functions and regular expressions to determine if we need to use JSON to store/retrieve the data, and if so, then we do.
52 CHAPTER 3: HTML5 Storage APIs
More important than how the preceding code works (which is relatively simple once you break it down) is how we will be able to use it. Basically, we now have three functions that permit more complex value storage at our disposal for interacting with the HTML5 Web Storage functionality:
PROWEBAPPS.Storage.get(key, scope) key is a string value used to identify the entry. scope can be optionally specified as "session" (i.e., as a string) if
you want to store to session storage instead of local storage. PROWEBAPPS.Storage.set(key, value, scope)
As per the get method, the key is a string value to identify the entry.
value is the data that we wish to save to Web Storage. (This can
be a simple value, array, object, etc.). Arrays and objects are serialized using JSON and then stored as strings.
scope (optional) specifies whether the key value will be saved to session or local storage. Passing no value to this parameter means that the value will be saved to local storage.
PROWEBAPPS.Storage.remove(key, scope) key is a string value used to specify the entry that will be
removed from storage. The scope parameter (if supplied) will specify whether session or
local storage should be used. If no value is supplied, then local storage is used by default.
Now that we have this functionality at our disposal, let’s have a look at storing simple JavaScript objects and arrays using our PROWEBAPPS.Storage functions. We’ll do this by creating our webstorage-test.js file, which will be used to power this little storage test application:
$(document).ready(function() { // read the data from local storage for the items var items = PROWEBAPPS.Storage.get("listitems"); var loadTicks = new Date().getTime();
function displayItems() { loadTicks = new Date().getTime();
$("#items li[class!='header']").remove(); if (items) {
// create list items to display the current items for (var ii = 0; ii < items.length; ii++) {
var itemAge = Math.floor((loadTicks - items[ii].created) / 1000); $("#items").append("<li>" + items[ii].title + " (created " + itemAge +
"s ago)</li>"); } // for }
CHAPTER 3: HTML5 Storage APIs
else { $("#items").append("<li>No items</li>");
// initialize the items array items = [];
} // if..else } // displayItems
// button click handlers go here displayItems();
}); The preceding code is very simple and is designed to retrieve an array of items
( listitems) from localStorage and display them on the screen. With the code as it was before (without add or clear functionality defined), loading the page generates HTML output, as displayed in Figure 3–2.
Figure 3–2. The Web Storage test application page As there are no items currently in storage (the PROWEBAPPS.Storage.get function
currently returns null), we display “No items” on the screen. Let’s implement the add and clear button click handlers to populate and save the array:
$("#add").click(function() { items.push({ title: $("#newtitle").val(), created: new Date().getTime()
// save the items
PROWEBAPPS.Storage.set("listitems", items);
displayItems();
54 CHAPTER 3: HTML5 Storage APIs
$("#clear").click(function() { items = null;
PROWEBAPPS.Storage.remove("listitems");
displayItems(); });
Once again, this is very simple code. In the case of the add handler, we push a new object onto the array using the title of the item and the current date time (represented in milliseconds), save the items to storage, and then refresh the display.
The clear handler is even simpler. We reset the items variable state back to null, remove listitems from local storage, and then update the display.