Beginning in Safari 4.0, Safari supports the HTML 5 client-side storage specification. One portion of that specification is key-value storage. The purposes of key-value storage are twofold:
To provide storage for cookie-like data specific to a single browser window.
To provide local storage that does not get retransmitted with every request to the server, thus making it practical to store larger quantities of data than are practical with cookies.
To support those goals, the HTML 5 specification provides two key-value storage objects: sessionStorage
and localStorage
.
The localStorage
and sessionStorage
JavaScript objects are functionally identical except in their persistence and scope rules:
localStorage
—used for long-term storage. This data persists after the window is closed and is shared across all browser windows.
sessionStorage
—used for ephemeral data related to a single browser window. Data stored in the sessionStorage
object does not persist after the window is closed and is not shared with other windows.
If a new browser window is created when the user clicks a link, that new window gets a copy of the sessionStorage
object as it exists at the time the window is created. The data is copied, not shared, however, so future changes made by either page are not reflected in the session storage for the other page.
Except for these differences, the localStorage
and sessionStorage
objects behave identically.
Like cookies, these objects provide different sets of data to pages served by different domains. Unlike cookies, the data is not transmitted back to the server during normal browsing. If you need to send the stored data back to the server, you must do so explicitly using JavaScript and an XMLHttpRequest
object.
Note: The underlying storage pool is not shared between the localStorage
and sessionStorage
objects. Thus, it is not possible to obtain a key stored with localStorage
by reading it from sessionStorage
or vice versa. To avoid confusion, you should generally not store the same key in both storage objects.
This section describes how to store, retrieve, and delete key-value pairs using the session storage or local storage objects. Because session storage and local storage objects behave similarly, the examples in this section all use session storage for consistency.
You can change these examples to use local storage by substituting the localStorage
object in place of the sessionStorage
object wherever it appears in the code.
To store a value in key-value storage, use the setItem
method. This method takes two parameters: a name and a value.
Consider a website that holds regular contests with various prizes. You might elect to store the user’s shirt size so that every time the user enters a contest that requests a shirt size, your JavaScript code can populate the shirt size field automatically with the last value chosen. You can store the value with the following line of code:
// Store the value of the variable "myShirtSize" into the |
// session storage field named "shirt_size". |
sessionStorage.setItem("shirt_size", myShirtSize); |
If you want to store the value in local storage, simply use the localStorage
object instead. For example:
localStorage.setItem("shirt_size", myShirtSize); |
Storing data can throw an exception if you exceed a browser-specific quota. If the data you are storing is important, you should check for this exception and handle it. For example:
try { |
sessionStorage.setItem("shirt_size", myShirtSize); |
} catch (e) { |
if (e == QUOTA_EXCEEDED_ERR) { |
alert('Quota exceeded.'); |
} |
} |
In your onload
method, you might then retrieve that value and populate the form field as appropriate with code like this:
var myShirtSize = sessionStorage.getItem("shirt_size"); |
// do something with the value here. |
document.getElementById('shirt_size').value = myShirtSize; |
If no key-value pair with the specified name exists, myShirtSize
is set to null
.
If your key name is a valid JavaScript token (no spaces, punctuation other than underscore, and so on), you can also retrieve the value like this:
var myShirtSize = sessionStorage.shirt_size; |
You can find out the total number of keys (for your domain) in session storage by examining the value stored in sessionStorage.length
. For example:
alert('there are '+sessionStorage.length+' items in the session storage array.'); |
Finally, you can obtain a key based on a numeric index.
var value; |
var index = 3; |
try { |
value = sessionStorage(index); |
} catch(e) { |
if (e == INDEX_SIZE_ERR) { |
alert('There are fewer than '+(index-1)+' keys in the session storage object.'); |
} |
} |
This method throws an exception if the index is not within the range [0..n-1]
where n
is the number of keys in the storage object.
There are two ways to delete values from key-value storage: individually or en masse. To delete a single value (continuing the shirt size example from the previous section), use the following line of code:
sessionStorage.removeItem("shirt_size"); |
To remove all key-value pairs for your domain, use the following line of code:
sessionStorage.clear(); |
Like cookies, storage objects are a shared resource common to web content served from the same domain. All pages from the same domain share the same local storage object. Frames and inline frames also share the same session storage object because they descend from the same window.
Because this resource is shared, scripts running in multiple page contexts can potentially modify the data stored in a storage object that is actively being scrutinized or modified by a script running on a different page. If your scripts do not notice these changes, you may not get the results you expect.
To this end, storage objects generate an event of type storage
whenever a script adds, deletes, or modifies a value in key-value storage so that your scripts can notice changes to local or session storage by other scripts and act on them.
Before you can receive storage events, you must first register for them by executing the following line of code:
window.addEventListener('storage', storage_handler, false); |
Once you have registered an event handler, the specified function (in this case, storage_handler
) is called whenever a script modifies either local or session storage. Here is a simple handler that shows an alert for each field in a storage
event:
function storage_handler(evt) |
{ |
alert('The modified key was '+evt.key); |
alert('The original value was '+evt.oldValue); |
alert('The new value is '+evt.newValue); |
alert('The URL of the page that made the change was '+evt.url); |
alert('The window where the change was made was '+evt.source); |
} |
This example, while simple, shows the five event fields relevant to a storage event. The fields are as follows:
key
The key that was modified. If the session or local storage object is wiped with the clear
method, the value of key
is null
.
oldValue
The previous value of the modified key. If the key is newly created, the value of oldValue
is null
. If the storage object is wiped with the clear
method, the value is also null
.
newValue
The current (new) value of the modified key. If the key is deleted with the clear
method, the value of key
is null
. If the storage object is wiped with the clear
method, the value is also null
.
url
The URL of the page that added, modified, or deleted the key. The url
field is only available if the page that made the change is in the same browsing context (a single tab in a single window). Otherwise, the url
field value will be null
.
source
The Window
object containing the script that modified the key. The source
field is only available if the page that made the change is in the same browsing context (a single tab in a single window). Otherwise, the source
field value will be null
.
This HTML page demonstrates local and session storage. If you modify the values in either field, they are stored locally (both on modification and on page exit) and are retrieved when you reload the page. If you close the window and then load the page again, only the value stored in local storage is restored.
This example is also included in the attached Companion Files archive.
<html> |
<head> |
<script language="JavaScript" type="text/javascript"><!-- |
function restoreValues() |
{ |
if (typeof(sessionStorage) == 'undefined' || typeof(localStorage) == 'undefined') { |
alert('local and session storage not supported by this browser.'); |
} |
document.getElementById('myfield1').value = sessionStorage.myfield1 ? sessionStorage.myfield1 : ""; |
document.getElementById('myfield2').value = localStorage.getItem('myfield2') ? localStorage.getItem('myfield2') : ""; |
// Save changes if the user leaves the page. |
window.onbeforeunload = function () { |
return saveChanges(); |
}; |
} |
function clearAll() |
{ |
sessionStorage.clear(); |
localStorage.clear(); |
restoreValues(); |
} |
function setValue(value) |
{ |
if (value == 'myfield1') { |
sessionStorage.setItem(value, document.getElementById(value).value); |
} else { |
localStorage.setItem(value, document.getElementById(value).value); |
} |
} |
function saveChanges() |
{ |
setValue('myfield1'); |
setValue('myfield2'); |
return NULL; |
} |
function clearValue(value) |
{ |
if (value == 'myfield1') { |
sessionStorage.removeItem(value); |
} else { |
localStorage.removeItem(value); |
} |
document.getElementById(value).value = ''; |
} |
--></script> |
</head> |
<body onload='restoreValues()'> |
<p>Field 1 is stored in session storage, field 2 in local storage. Both should be retrieved on a page reload, but field 1 should not be retrieved if you close the window and reopen it.</p> |
<p> |
<input id='myfield1' onchange='setValue("myfield1")'>Field 1</input><br /> |
<input id='myfield2' onchange='setValue("myfield2")'>Field 2</input> |
</p> |
<p> |
<a href='#' onclick='clearValue("myfield1")'>clear value 1</a><br /> |
<a href='#' onclick='clearValue("myfield2")'>clear value 2</a><br /> |
<a href='#' onclick='clearAll()'>clear all</a><br /> |
</p> |
</body> |
</html> |
Key-value storage is no more concurrency-safe than cookies. Most JavaScript code tends to perform work in response to user actions, which means there is little actual concurrency involved. However, if your code needs to do regularly read and write to session storage objects for other purposes, you must do a bit of extra work.
Last updated: 2010-01-20