Saving Preferences with localStorage

0
158

The localStorage mechanism provides a very simple method for developers to persist data on the client’s machine. The localStorage mechanism Is simply a name/value store built In to the web browser.

Information stored In localStorage persists between browser sessions and can’t be read by other websites, because It’s restricted to the domain you’re currently visiting

AwesomeCo Is In the process of developing a new customer service portal and wants users to be able to change the text size, background, and text color of the site. Let’s Implement that using localStorage so that when we save the changes, they persist from one browser session to the next. When we’re done, we’ll end up with a prototype that looks like Figure 9.1, on the following page.

Building the Preferences Form

Let’s craft a form using some semantic HTML5 markup and some of the new form controls you learned about In Chapter 3, Creating User- Friendly Web Forms, on page 45. We want to let the user change the foreground color, change the background color, and adjust their font size.

<pxstrong>Preferences</strongx/p>
<form id= “preferences” action =”save_prefs”
method=”post” accept-charset=”utf-8″>
<fieldset id=”colors” class=””>
<1egend>Colo rs</legencb
<ol>
< l i >
<label for=”background_color”>Background color</label>
<input type=”co7or” name=”background_color”
v a l u e = ” ” id= “background_color”>
</li>

<li>
<label for=”text_color”>Text color</label>
<input type=”co7or” name=”text_color”
v a l u e = ” ” id=”text_color”>
</li>
<li>
<label for=”text_size”>Text size</label>
<select name=”text_size” id=”text_size”>
<option value=”16″>16px</option>
<option value=”20″>20px</option>
<option value=”24″>24px</option>
<option value=”32″>32px</option>
</select>
</ol>
</fieldset>
<input type=”submit” value=”Save changes”»
</form>

We’ll just use HTML color codes for the color.

Saving and Loading the Settings

To work with the localStorage system, you use JavaScript to access the window.localStorageO object. Setting a name and value pair is as simple as this:

l o c a l Storage . setItem(“background_color” , $(“#background_color”) .val O) ;

Grabbing a value back out is just as easy.

var bgcolor = 1ocalStorage.getltemC”background_color”);

Let’s create a method for saving all the settings from the form.

f u n c t i o n s a v e _ s e t t i n g s ( ) {
l o c a l Storage.setltemC”background_color”, $(“#background_color”).val());
l o c a l S t o r a g e . s e t l t e m C”text_color”, $ ( ” # t e x t _ c o 7 o r ” ) . v a l ( ) ) ;
l o c a l Storage.setltemC”text_size”, $(“#text_size”).val());
a p p l y _ p r e f e r e n c e s _ t o _ p a g e ( ) ;
}

Next, let’s build a similar method that will load the data from the local- Storage system and place it into the form fields.

f u n c t i o n l o a d _ s e t t i n g s ( ) {
var bgcolor = 1ocalStorage.getltemC”background_color”) ;
var t e x t _ c o l o r = l o c a l S t o r a g e . g e t l t e m C ” t e x t _ c o 7 o r ” ) ;
var t e x t _ s i z e = 1ocalStorage.getltemC”text_size”) ;
$C’#background_color”) .val Cbgcolor) ;
$ C ” # t e x t _ c o 7 o r ” ) . v a l C t e x t _ c o l o r ) ;
$(“#text_size”).valCtext_size);
a p p l y _ p r e f e r e n c e s _ t o _ p a g e O ;
}

This method also calls a method that will apply the settings to the page itself, which we’ll write next.

Applying the Settings

Now that we can retrieve the settings from localStorage, we need to apply them to the page. The preferences we’re working with are all related to CSS in some way, and we can use jQuery to modify any element’s styles.

f u n c t i o n a p p l y _ p r e f e r e n c e s _ t o _ p a g e O{
SC’body”) .cssC’backgroundColor” , $C’#background_color”) .val O) ;
$C’body”) . c s s C ” c o 7 o r ” , $ C ” # t e x t _ c o 7 o r ” ) . v a l O) ;
SC’body”) .cssC’fontSize” , $C’#text_size”) . v a l O + “px”) ;
}

Finally, we need to fire all of this when the document is ready.

$ ( f u n c t i o n O {
l o a d _ s e t t i n g s O ;
$ C ‘ f o r m # p r e f e r e n c e s ‘ ) . s u b m i t ( f u n c t i o n ( e v e n t ) {
e v e n t . p r e v e n t D e f a u l t ( ) ;
s a v e _ s e t t i n g s O ;
} ) ;

Falling Back

The localStorage method works only on the latest Internet Explorer, Firefox, Chrome, and Safari, so we’ll need a fallback method for older browsers. We have a couple of approaches.  We can save the information on the server, or we persist the preferences on the client side using cookies.

Server-Side Storage

If you have user accounts in your system, consider making the preferences page persist the settings to the user’s record in your application. When they log in, you can check to see whether any client-side settings exist and, if they don’t, load them from the server. This way, your users keep their settings across browsers and across computers.

To persist to the server, simply ensure your form posts to the server—don’t prevent the default submit behavior with JavaScript if there’s no support for cookies.

Server-side storage is really the only method that will work if the user disables JavaScript, because you could code your application to fetch the settings from the database and not the localStorage hash. Also, this is the only approach you can take if you’re storing more than 4KB of data, since that’s the maximum amount of data you can store in a cookie.

Cookies and JavaScript

The tried-and-true combination of cookies and JavaScript can act as a decent fallback. Using the well-known cookie script from Quirksmode,5 we can build our own localStorage fallback solution.

Detecting localStorage support In the browser Is pretty simple. We just check for the existence of a localStorage method on the window object:

i f ( ! w i n d o w . l o c a l S t o r a g e ){
}
Next, we need methods to write the cookies, which we’ll borrow from
the Quirksmode article. Add these JavaScript functions to your script
block, within the braces:

f u n c t i o n c r e a t e C o o k i e C n a m e , v a l u e , d a y s ) {
i f (days) {
v a r date = new D a t e O ;
d a t e . s e t T i m e ( d a t e . g e t T i m e ( ) + ( d a y s * 2 4 * 6 0 * 6 0 * 1 0 0 0 ) ) ;
v a r e x p i r e s = “; e x p i r e s = ” + d a t e . t o G M T S t r i n g C ) ;
}
e l s e var e x p i r e s = ” ” ;
d o c u m e n t . c o o k i e = n a m e + ” = ” + v a l u e + e x p i r e s + ” ; path=/”;
}
f u n c t i o n readCookie(name) {
v a r r e s u l t = “”
v a r nameEQ = name + ” = ” ;
v a r ca = d o c u m e n t . c o o k i e . s p l i t C ; ‘ ) ;
f o r C v a r i = 0 ; i < c a . l e n g t h ; i + + ) {
v a r c = c a [ i ] ;
w h i l e ( c . c h a r A t ( 0 ) = = ‘ ‘) c = c . s u b s t r i n g ( l , c . l e n g t h ) ;
i f (c.indexOf(nameEQ) == 0 ) {
r e s u l t = c . s u b s t r i n g C n a m e E Q . l e n g t h , c . l e n g t h ) ;
} e l s e {
r e s u l t = “” ;
}
}
r e t u r n ( r e s u l t ) ;
}

Finally, we want to make a localStorage object that uses the cookies as Its back end. A very hackish example that just barely makes this work might look like this:

Une l l o c a l S t o r a g e = ( f u n c t i o n () {
r e t u r n {
s e t l t e m : f u n c t i o n (key, v a l u e ) {
c r e a t e C o o k i e ( k e y , v a l u e , 3000)
5 },

We can use localStorage for things that we want to persist even after our users close their web browsers, but sometimes we need a way to store some information while the browser is open and throw it away once the session is over. That’s where sessionStorage comes into play. It works the same way as localStorage, but the contents of the sessionStorage are cleared out once the browser session ends. Instead of grabbing the localStorage object, you grab the sessionStorage object.

s e s s i o n S t o r a g e . s e t l t e m C ‘ n a m e ‘ , ‘Brian Hogan’);
var name = s e s s i o n S t o r a g e . g e t l t e m C ‘name ‘) ;

Creating a fallback solution for this is as simple as ensuring that the cookies you create expire when the browser closes.

g e t l t e m : f u n c t i o n (key) {
r e t u r n ( r e a d C o o k i e ( k e y ) ) ;
}
};
} )  ;

Take note of line 4. We’re creating a cookie with an expiration date of 3,000 days from now. We can’t create cookies that never expire, so I’m setting this to a ridiculously long time into the future.

We’ve kept the basic implementation of localStorage the same from the outside. If you need to remove items or clear everything out, you’ll need to get a little more creative. Ideally, in the near future, we can remove this hackish solution and rely only on the browser’s localStorage()
methods.