Web Storage

Contact Us or call 1-877-932-8228
Web Storage

Web Storage

HTML5 Web storage is used to store key-value pair data throughout a single session (sessionStorage) or between sessions (localStorage). Browsers typically limit the amount of client-side storage space allocated to a single domain to 5 megabytes and throw a QUOTA_EXCEEDED_ERR exception if you try to store more than that.

The methods and properties are the same for working with sessionStorage and localStorage and are shown below:

Web Storage Methods and Properties
Method/Property Description
length Holds the number of key/value pairs.
setItem(key,value) Creates or updates a key/value pair.
getItem(key) Gets the value of the specified key.
key(n) Returns the nth key. Useful for iterating through key/value pairs.
removeItem(key) Removes the key/value pair for the given key.
clear() Removes all key/value pairs.

Browser Support

The following browsers support Web Storage:

  1. Internet Explorer 8+
  2. Firefox 3.5+
  3. Chrome 4.0+
  4. Safari 4.0+
  5. Opera 10.5+

Internet Explorer and Firefox do not support web storage unless the files are delivered by a web server. So unless you have a web server (e.g., IIS or Apache) set up locally, you should use Safari, Chrome or Opera for the demos and exercises in this lesson.

Local Storage

Local storage is used for maintaining state during and between sessions. It is easiest to understand through a simple example:

  1. Open html5-storage/Demos/local-storage.html in your browser: Local Storage
  2. Enter a key/value pair and press the Save button. The table should update: Local Storage
  3. Add some more key/value pairs: Local Storage
  4. Refresh your browser. The values you entered should still be in the table.
  5. Close and reopen your browser. The values you entered should still be in the table.
  6. Enter a key that you have already entered, but change the value. Press Save. The table should update: Local Storage
  7. Press the Delete button next to one of your key/value pairs. It should (after you bypass the warning) be removed from the table and stay removed if you refresh or close and open your browser.
  8. Press the Clear All button below the table. All key/value pairs should (after you bypass the warning) be removed from the table and stay removed if you refresh or close and open your browser.

Let's take a look at the code starting with the HTML in the <body>:

<label for="key">Key:</label>
<input type="text" id="key" autofocus autocomplete="off">
<label for="value">Value:</label>
<input type="text" id="value" autocomplete="off">
<button onclick="save()">Save</button>
<hr>
<table>
	<thead>
		<tr>
			<th>#</th>
			<th>key</th>
			<th>value</th>
			<th>Delete</th>
		</tr>
	</thead>
	<tbody id="output">
		<tr>
			<td colspan="4">Nothing to Show</td>
		</tr>
	</tbody>
</table>
<button onclick="clearStorage()">Clear All</button>

Things to notice:

  1. We will use the ids of the input elements to get the user-entered values.
  2. The Save button calls the save() function.
  3. The Clear All button calls the clearStorage() function.
  4. We will update the rows in the tbody element to show the key/value pairs in localStorage.

Now let's look at the JavaScript, starting with the updateTable() function, which is called when the page loads and each time we set or remove an item from localStorage:

window.addEventListener("load",updateTable,false);

function updateTable() {
	var tbody = document.getElementById("output");
	while (tbody.getElementsByTagName("tr").length > 0) {
		tbody.deleteRow(0);
	}
	var row;
	if (localStorage.length==0) {
		row = tbody.insertRow(i);
		cell = row.insertCell(0);
		cell.colSpan="4";
		cell.innerHTML = "Nothing to Show";
	}
	for (var i=0; i < localStorage.length; ++i) {
		row = tbody.insertRow(i);
		cell = row.insertCell(0);
		cell.innerHTML = i;
		cell = row.insertCell(1);
		cell.innerHTML = localStorage.key(i);
		cell = row.insertCell(2);
		cell.innerHTML = localStorage.getItem(localStorage.key(i));
		cell = row.insertCell(3);
		cell.innerHTML = "<img src='Images/delete.png' onclick='deleteItem(\"" + localStorage.key(i) + "\")'>";
	}
}

Things to notice:

  1. We use the standard table element methods to remove all the table rows in the tbody.
  2. If the localStorage is empty (localStorage.length==0) then we create a single row that reads "Nothing to Show".
  3. If the localStorage is not empty, we loop through it and create a row for each key/value pair.
  4. Note that when the delete image is clicked, the deleteItem() function is called and the key for that key/value pair is passed in.

Now let's look at the remaining functions:

function deleteItem(key) {
	if (!confirm("Are you sure you want to delete this item?")) return;
	localStorage.removeItem(key);
	updateTable();
}

function clearStorage() {
	if (!confirm("Are you sure you want to delete all local storage for this domain?")) return;
	localStorage.clear();
	updateTable();
}

function save() {
	var key = document.getElementById("key").value;
	var value = document.getElementById("value").value;
	localStorage.setItem(key,value);
	updateTable();
}

Things to notice:

  1. The deleteItem() function uses localStorage.removeItem(key) to remove the passed-in key.
  2. The clearStorage() function uses localStorage.clear() to empty localStorage.
  3. The save() function uses localStorage.setItem(key,value) to add or update a key/value pair.
  4. All three functions call updateTable() after they run so that the page gets updated.

And that's all there is to localStorage.

Use Case

A good use case for localStorage is saving data in a large form (for example - a job application) to finish and submit later. This way, you don't have to clog up your database server with half-completed applications.

Session Storage

And here's the beauty of it: sessionStorage is exactly the same. You can literally use find and replace to change "localStorage" to "sessionStorage" and your page will continue to work. The only difference is that your key/value pairs will only be accessible for the life of the session. So, if you close and reopen your browser, your key/value pairs will be gone.

To test this, go through the same process we went through to test localStorage, but use html5-storage/Demos/session-storage.html instead.

Browsers are free to maintain a session longer than a single visit. For example, if the browser crashes, the browser may try to restore the session, in which case it may be able to keep the key/value pairs in sessionStorage.

Use Case

A good use case for sessionStorage is auto-saving forms so that if a user accidentally refreshes the browser, he/she doesn't lose any data. We'll tackle this in the upcoming exercise.

Prefixing your Keys

As it's possible to have multiple applications fed from the same origin (think URL), it's a good idea to use prefixes to scope your keys to a specific application. Take a look at the following demo:

Code Sample:

html5-storage/Demos/questions.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
window.addEventListener("load",updateList,false);

var prefix="q-";

function updateList() {
	var questions="<ol>";
	for (var i=0; i < localStorage.length; ++i)  {
		if (localStorage.key(i).substring(0,prefix.length) == prefix) {
			questions+="<li>" + localStorage.key(i) .substring(prefix.length) + " <img onclick=\"showAnswer('" + localStorage.key(i) + "')\" src='Images/find.png'> <img onclick=\"deleteQuestion('" + localStorage.key(i) + "')\" src='Images/delete.png'></li>";		
		}
	}
	questions+="</ol>";
	document.getElementById("questions").innerHTML = questions;
}

function save() {
	var q = prefix + document.getElementById("q").value;
	var a = document.getElementById("a").value;
	localStorage.setItem(q,a);
	document.getElementById("q").value="";
	document.getElementById("a").value="";
	document.getElementById("q").focus();
	updateList();
}

function revealLocalStorage() {
	var questions="<ol>";
	for (var i=0; i < localStorage.length; ++i)  {
		questions+="<li>" + localStorage.key(i) + ": " + localStorage.getItem(localStorage.key(i)) + "</li>";	
	}
	questions+="</ol>";
	document.getElementById("questions").innerHTML = questions;
}

function showAnswer(key) {
	alert(localStorage.getItem(key));	
}

function deleteQuestion(key) {
	if (!confirm("Are you sure you want to delete this question?")) return;
	localStorage.removeItem(key);
	updateList();
}

function deleteQuestions() {
	if (!confirm("Are you sure you want to delete all questions?")) return;
	
	var numItems = localStorage.length;
	for (var i=numItems-1; i >=0; --i)  {
		if (localStorage.key(i).substring(0,prefix.length) == prefix) {
			localStorage.removeItem(localStorage.key(i));
		}
	}
	updateList();
}
</script>
</head>
<body>
<label for="q">Question:</label>
<input type="text" id="q" autofocus autocomplete="off">
<label for="a">Answer:</label>
<input type="text" id="a" autocomplete="off">
<button onclick="save()">Save</button>
<output id="questions"></output>
<menu>
	<button onclick="revealLocalStorage()">Show All Local Storage</button>
	<button onclick="updateList()">Show Questions</button>
	<button onclick="deleteQuestions()">Delete All Questions</button>
</menu>
</body>
</html>

This is very similar to the page we saw earlier. It just prepends a prefix to the key, so that key used in other applications fed from the same domain don't get overwritten. It also adds a convenient feature of emptying the question and answer and replacing the cursor in the question.

Next