C H A P T E R  39

Using Web Storage

Web storage allows us to store simple key/value data in the browser. Wen storage is similar to cookies, but better implemented and we can store greater amounts of data. There are two kinds of web storage – local storage and session storage. Both types share the same mechanism, but the visibility of the stored data and its longevity differ. Table 39-1 provides the summary for this chapter.

Image Tip There is another storage specification, the Indexed Database API, which allows richer data storage and SQL-like queries. This specification is still volatile and the browser implementations are experimental and unstable as I write this.

Image

Using Local Storage

We access the local storage feature through the localStorage global property – this property returns a Storage object, which is described in Table 39-2. The Storage object is used to store pairs of strings, organized in key/value form.

Image

The Storage object allows us to store key/value pairs where both the key and the value are strings. Keys must be unique, which means the value is updated if we call the setItem method using a key that already exists in the Storage object. Listing 39-1 shows how we can add, modify, and clear the data in the local storage.

Listing 39-1. Working with local storage

<!DOCTYPE HTML>
<html>
    <head>
        <title>Example</title>
        <style>
            body > * {float: left;}
            table {border-collapse: collapse; margin-left: 50px}
            th, td {padding: 4px;}
            th {text-align: right;}
            input {border: thin solid black; padding: 2px;}
            label {min-width: 50px; display: inline-block; text-align: right;}
            #countmsg, #buttons {margin-left: 50px; margin-top: 5px; margin-bottom: 5px;}
        </style>
    </head>
    <body>
        <div>
            <div><label>Key:</label><input id="key" placeholder="Enter Key"/></div>
            <div><label>Value:</label><input id="value" placeholder="Enter Value"/></div>
            <div id="buttons">
                <button id="add">Add</button>
                <button id="clear">Clear</button>
            </div>
            <p id="countmsg">There are <span id="count"></span> items</p>
        </div>

        <table id="data" border="1">
            <tr><th>Item Count:</th><td id="count">-</td></tr>
        </table>

        <script>
            displayData();

            var buttons = document.getElementsByTagName("button");
            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = handleButtonPress;
            }

            function handleButtonPress(e) {
                switch (e.target.id) {
                    case 'add':
                        var key = document.getElementById("key").value;
                        var value = document.getElementById("value").value;
                        localStorage.setItem(key, value);
                        break;
                    case 'clear':
                        localStorage.clear();
                        break;
                }
                displayData();
            }

            function displayData() {
                var tableElem = document.getElementById("data");
                tableElem.innerHTML = "";
                var itemCount = localStorage.length;
                document.getElementById("count").innerHTML = itemCount;
                for (var i = 0; i < itemCount; i++) {
                    var key = localStorage.key(i);
                    var val = localStorage[key];
                    tableElem.innerHTML += "<tr><th>" + key + ":</th><td>"
                        + val + "</td></tr>";
                }
            }
        </script>
    </body>
</html>

In this example, I report on the number of items in the local storage and enumerate the set of stored name/value pairs to populate a table element. I have added two input elements, and I use their contents to store items when the Add button is pressed. In response to the Clear button, I clear the contents of the local storage. You can see the effect in Figure 39-1.

Image

Figure 39-1. Working with local storage

The browser won't delete the data we add using the localStorage object unless the user clears the browsing data. (The specification also allows the data to be removed for security reasons, but the kind of security problems that require local data to be deleted are not articulated.)

Listening for Storage Events

The data stored via the local storage feature is available to any document that has the same origin. The storage event is triggered when one document makes a change to the local storage and we can listen to this event in other documents from the same origin to make sure that we stay abreast of changes.

The object dispatched with the storage event is a StorageEvent object, whose members are described in Table 39-3.

Image

Listing 39-2 shows a document, which I have saved as storage.html, that listens and catalogues the events issued by the local storage object.

Listing 39-2. Cataloguing local storage events

<!DOCTYPE HTML>
<html>
    <head>
        <title>Storage</title>
        <style>
            table {border-collapse: collapse;}
            th, td {padding: 4px;}
        </style>
    </head>
    <body>
        <table id="data" border="1">
            <tr>
                <th>key</th>
                <th>oldValue</th>
                <th>newValue</th>
                <th>url</th>
                <th>storageArea</th>
            </tr>
        </table>
        <script>
            var tableElem = document.getElementById("data");

            window.onstorage = handleStorage;

            function handleStorage(e) {
                var row = "<tr>";
                row += "<td>" + e.key + "</td>";
                row += "<td>" + e.oldValue + "</td>";
                row += "<td>" + e.newValue + "</td>";
                row += "<td>" + e.url + "</td>";
                row += "<td>" + (e.storageArea == localStorage) + "</td></tr>";
                tableElem.innerHTML += row;
            };
        </script>
    </body>
</html>

The storage event is triggered through the Window object of any document that shares the changed storage. In this example, I add a new row to a table element each time an event is received – you can see the effect in Figure 39-2.

Image

Figure 39-2. Displaying the details of storage events

The events in the figure show me adding new items to local storage. The sequence was:

  • Add a new pair: Banana/Yellow
  • Add a new pair: Apple/Red
  • Update the value associated with Apple to Green
  • Add a new pair: Cherry/Red
  • Press the Clear button (which calls the clear method)

You can see that null is used when there is no value to report in the event. For example, when I add a new item to storage, the oldValue property returns null. The last event in the table has the key, oldValue, and newValue properties as null. This is the event that was triggered in response to the clear method being called, which removes all of the items from storage.

The url property helpfully tells us which document has triggered the change. The storageArea property returns the Storage object that has changed, which can be the local or session storage objects (I'll explain session storage shortly). For this example, we only receive events from the local storage object.

Image Note Events are not dispatched within the document that made the change. I guess it is assumed that we already know what happened. The events are only available in other documents from the same origin.

Using Session Storage

Session storage works just like local storage, except that the data is private to each browsing context and is removed when the document is closed. We access session storage through the sessionStorage global variable, which returns a Storage object (previously described in Table 39-2). You can see session storage in use in Listing 39-3.

Listing 39-3. Using session storage

<!DOCTYPE HTML>
<html>
    <head>
        <title>Example</title>
        <style>
            body > * {float: left;}
            table {border-collapse: collapse; margin-left: 50px}
            th, td {padding: 4px;}
            th {text-align: right;}
            input {border: thin solid black; padding: 2px;}
            label {min-width: 50px; display: inline-block; text-align: right;}
            #countmsg, #buttons {margin-left: 50px; margin-top: 5px; margin-bottom: 5px;}
        </style>
    </head>
    <body>
        <div>
            <div><label>Key:</label><input id="key" placeholder="Enter Key"/></div>
            <div><label>Value:</label><input id="value" placeholder="Enter Value"/></div>
            <div id="buttons">
                <button id="add">Add</button>
                <button id="clear">Clear</button>
            </div>
            <p id="countmsg">There are <span id="count"></span> items</p>
        </div>

        <table id="data" border="1">
            <tr><th>Item Count:</th><td id="count">-</td></tr>
        </table>

        <script>
            displayData();

            var buttons = document.getElementsByTagName("button");
            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = handleButtonPress;
            }

            function handleButtonPress(e) {
                switch (e.target.id) {
                    case 'add':
                        var key = document.getElementById("key").value;
                        var value = document.getElementById("value").value;
                        sessionStorage.setItem(key, value);
                        break;
                    case 'clear':
                        sessionStorage.clear();
                        break;
                }
                displayData();
            }

            function displayData() {
                var tableElem = document.getElementById("data");
                tableElem.innerHTML = "";
                var itemCount = sessionStorage.length;
                document.getElementById("count").innerHTML = itemCount;
                for (var i = 0; i < itemCount; i++) {
                    var key = sessionStorage.key(i);
                    var val = sessionStorage[key];
                    tableElem.innerHTML += "<tr><th>" + key + ":</th><td>"
                        + val + "</td></tr>";
                }
            }
        </script>
    </body>
</html>

This example works in the same way as the one for local storage, except the visibility and life are restricted. These restrictions have a consequence on how the storage event is dealt with – remember that storage events are only triggered for documents that share storage. In the case of session storage, this means that the events will be triggered only for embedded documents, such as those in an iframe. Listing 39-4 shows an iframe added to the previous example which contains the storage.html document.

Listing 39-4. Using storage events with session storage

<!DOCTYPE HTML>
<html>
    <head>
        <title>Example</title>
        <style>
            body > * {float: left;}
            table {border-collapse: collapse; margin-left: 50px}
            th, td {padding: 4px;}
            th {text-align: right;}
            input {border: thin solid black; padding: 2px;}
            label {min-width: 50px; display: inline-block; text-align: right;}
            #countmsg, #buttons {margin-left: 50px; margin-top: 5px; margin-bottom: 5px;}
            iframe {clear: left;}
        </style>
    </head>
    <body>
        <div>
            <div><label>Key:</label><input id="key" placeholder="Enter Key"/></div>
            <div><label>Value:</label><input id="value" placeholder="Enter Value"/></div>
            <div id="buttons">
                <button id="add">Add</button>
                <button id="clear">Clear</button>
            </div>
            <p id="countmsg">There are <span id="count"></span> items</p>
        </div>

        <table id="data" border="1">
            <tr><th>Item Count:</th><td id="count">-</td></tr>
        </table>

        <iframe src="storage.html" width="500" height="175"></iframe>

        <script>
            displayData();

            var buttons = document.getElementsByTagName("button");
            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = handleButtonPress;
            }

            function handleButtonPress(e) {
                switch (e.target.id) {
                    case 'add':
                        var key = document.getElementById("key").value;
                        var value = document.getElementById("value").value;
                        sessionStorage.setItem(key, value);
                        break;
                    case 'clear':
                        sessionStorage.clear();
                        break;
                }
                displayData();
            }

            function displayData() {
                var tableElem = document.getElementById("data");
                tableElem.innerHTML = "";
                var itemCount = sessionStorage.length;
                document.getElementById("count").innerHTML = itemCount;
                for (var i = 0; i < itemCount; i++) {
                    var key = sessionStorage.key(i);
                    var val = sessionStorage[key];
                    tableElem.innerHTML += "<tr><th>" + key + ":</th><td>"
                        + val + "</td></tr>";
                }
            }
        </script>
    </body>
</html>

You can see how the events are reported in Figure 39-3.

Image

Figure 39-3. Storage events from session storage

Summary

In this chapter, I have described the web storage feature, which allows us to store key/value pairs in the browser. This is a simple feature, but the longevity of local storage can make it especially useful, particularly for storing simple user preferences.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.249.127