Lesson 14: Offline Storage in HTML5

html5_13_opener.psd

In this lesson, you will learn how offline storage works in HTML5, and how you can use it to store information gathered from the Internet onto your desktop or mobile device.

What you’ll learn in this lesson:

  • About the Application Cache API and how to cache files with HTML5
  • About the manifest file and how web pages are stored for offline use
  • To create your first offline web application
  • To manage offline files using HTML5 storage

Starting up

You will work with several files from the HTML5_14lessons folder in this lesson. Make sure you have loaded the HTML5lessons folder onto your hard drive from www.digitalclassroombooks.com/HTML5. See “Loading lesson files” in the Starting Up section of this book.

On the road, again

Certain jobs require people to travel to locations out of reach of the Internet. For individuals who rely on the Internet to keep track of information gathered (such as clients, purchase orders, comments regarding the trip, and so on), being out of reach of the Internet can result in a cumbersome process that requires the individual to somehow annotate all the information gathered, and later manually post it onto the company’s website. HTML5 offers offline storage capabilities, thus turning the out-of-reach website into a mobile application that stores data on the individual’s computer or mobile device when access to the Internet is not possible, and later transmits that data when access is possible again.

Offline storage in HTML5

There are primarily two offline capabilities in HTML5: application caching and offline storage. Application caching saves an application’s core logic and user-interface. Offline storage (or client-side storage) captures data generated by the user and specific resources the user is interested in. This lesson explains offline storage first. Application caching is explained later in the lesson.

HTML5 storage comprises several techniques to store data locally, from simple key/value pair caching, to file storage and SQL database stores. The technique you choose depends on the objective of the application and type of data stored.

In all cases, the data stored is directly connected to the origin of the site that creates it. In other words, data stored by one domain cannot be accessed from another domain. For example, AGI Training might have a number of web applications that store data. You can share data between these applications because they all originate from agitraining.com, but no outside application or website can read them.

HTML5 storage types

HTML5 storage saves data in named key/value pairs, much as browser cookies. Data is never transmitted back to a server, and HTML5 storage can accumulate a large amount of data (5Mb in FireFox, Chrome, Safari, and Opera, and up to 10Mb in IE 9+).

There are two kinds of global storage objects: sessionStorage and localStorage.

sessionStorage

Data stored with sessionStorage only lasts for the duration of the current browser session. Once you close the browser window or navigate away from the website, the local data is cleared.

localStorage

localStorage is a persistent version of sessionStorage: you can store data on the computer until it is explicitly removed by the application or the user.

Use the localStorage object on the global window object to access HTML5 storage. To detect whether a browser supports this feature, you need to create a web page and add the following JavaScript function:

function supports_html5_storage() {

try {

return 'localStorage' in window && window['localStorage'] != null;

} catch (e) {

return false;

}

}

This function returns a Boolean value of true if your browser supports HTML5 storage. Use the in modifier to easily determine whether an object contains another object.

localStorage methods

setItem(key, value)

Saves a value under a new key name or updates a value for an existing key.

getItem(key)

Retrieves the value for a given key name.

removeItem(key)

Deletes an entry in the data store for the given key name.

clear()

Deletes all key/value pairs in the data store for the current application.

length

Read-only property that returns the number of keys in a data store.

localStorage example

In this exercise, you will create a live application that saves to a local storage object data that the user enters. Source code is available in notepad_example.html in the HTML5_14lessons folder; the full listing is presented after this exercise.

1 In your text editor, open a new file and enter the markup to define a simple HTML5 page:

<!DOCTYPE html>

<html>

<head>

</head>

<body>

<section>

</section>

</body>

</html>

2 Insert a <style> section in the <head> section you created in step 1. You will make the text input area appear as a yellow sticky-note with a dashed border:

<head>

<style type="text/css">

#note{

width: 320px;

height: 200px;

background: LightYellow;

border: 1px dashed gray;

overflow-y: scroll;

padding: 4px;

font: normal gray 13px Arial;

}

</style>

</head>

3 Change the <body> tag to include an onload event that calls an initialize function. This function will set up the local storage object when the page finishes loading:

<body onload="initialize()">

4 The page will consist of an input area for the notepad and a reset button within the <section> element. Add a <div> tag and an <a href> tag to the <section> element:

<section>

<div id="note" contenteditable="true">

(Enter some text, close your browser and reload this page.)

</div>

<a href="#" onclick="reset_note();return false">Reset Note</a>

</section>

7845.jpg For this exercise, use the contenteditable property of a <div> for the input area, instead of creating a <textarea> form tag.

7854.jpg Due to the page size of this book, some code will appear on a second line. All code in single quotes should be entered on one line in an editor.

5 Add a <script> area at the top of the <section> element for the initialize() function and several global variables:

<section>

<script type="text/javascript">

var noteref, mystorage;

var defaulthtml = '<div id="note" contenteditable="false">(Enter some text, close your browser and then open this page again.)</div> ';

function initialize() {

<div id="note" contenteditable="true">

6 Within the initialize function, enter the code to call the function that checks whether your browser supports HTML5 storage:

function initialize {

if (supports_html5_storage()) {

// save a reference to the note area

7 Add the following line of code so when the value of the previous If statement is true, you obtain a reference to the <div> element using getElementById:

if (supports_html5_storage()) {

// save a reference to the note area

noteref = document.getElementById("note");

8 You need to get an instance of the browser’s local storage object. Depending on your browser, local storage might be defined as localStorage or globalStorage. The following code covers either variation and should be written on one line in your editor:

noteref = document.getElementById("note");

mystorage = window.localStorage ||

(window.globalStorage ? globalStorage[location.hostname] : null);

7861.jpg The code shown above obtains the storage object from window.localStorage or from window.globalStorage (“or” is symbolized by the two pipes ||). The second line is an immediate if clause. This statement determines whether the window.globalStorage object exists, and if so (symbolized by the question mark ?), returns the globalStorage object for your web host. The null value is used to represent the absence of the globalStorage object (symbolized by the colon :). So, if globalStorage is the default storage object, then retrieve the object from the current browser instance, location.hostname; otherwise, return null.

9 Now that you have a storage object, check whether there is a note stored from a previous session; if so, load its value into the text area from the name/value key pair:

if (supports_html5_storage()) {

// save a reference to the note area

noteref = document.getElementById("note");

mystorage = window.localStorage || (window.globalStorage ? globalStorage[location.hostname] : null);

if (mystorage) {

// if there is a note already stored

if (mystorage.notedata) {

// re-load it

noteref.innerHTML = mystorage.notedata;

}

To save the data, the user types into the local storage object. Use the KeyUp event and write a closure function to automatically save text to the storage object at the same time the user types a note:

noteref.innerHTML = mystorage.notedata;

}

// capture keystrokes and save to local data store

noteref.onkeyup = function (e) {

mystorage.notedata = this.innerHTML;

}

Notice you are not using setItem("notedata", this.innerHTML). This is because you can assign and retrieve variables as associative arrays, just as with any other JavaScript object.

Putting it all together

Here is the complete source code for the simple notepad example found in the HTML5_14lesson folder named notepad_example.html.

<!DOCTYPE html>

<html lang="en">

<head>

<style type="text/css">

#note{

width: 320px;

height: 200px;

background: LightYellow;

border: 1px dashed gray;

overflow-y: scroll;

padding: 4px;

font: normal gray 13px Arial;

}

</style>

</head>

<body onload="initialize()">

<section>

<script type="text/javascript">

var noteref, mystorage;

var defaulthtml = '<div id="note" contenteditable="false"> (Enter some text, close your browser and then open this page again.) </div> ';

function initialize() {

if (supports_html5_storage()) {

noteref = document.getElementById("note");

mystorage = window.localStorage ||

(window.globalStorage ? globalStorage[location.hostname] : null);

if (mystorage) {

// if there is a note already stored

if (mystorage.notedata) {

// re-load it

noteref.innerHTML = mystorage.notedata;

}

// capture keystrokes and save to local data store

noteref.onkeyup = function (e) {

mystorage.notedata = this.innerHTML;

}

7867.jpg It is important to enter all of the closing braces ‘}’ to match the opening braces ‘{’ for each function and if statement.

10 Add an else condition to the if statement to notify the user if local storage is not available. Also, add the function to check whether local storage is available. We’ll also add a label above the editor using a <div> tag. Add the following code and be sure the quoted string in the alert() function appears on one line in your editor:

mystorage.notedata = this.innerHTML;

}

}

} else {

alert('local storage not available with your browser.'),

}

}

function supports_html5_storage() {

try {

return 'localStorage' in window && window['localStorage'] != null;

} catch (e) {

return false;

}

}

</script>

<div>Note to self:</div>

<div id="note" contenteditable="true">

(Enter some text, close your browser and reload this page.)

</div>

</section>

</body>

</html>

Test your code in a browser that supports HTML5 storage; anything you type in the text area should be automatically saved in the local storage area. Please note that some browsers require the file to be uploaded to a web server before localStorage will function properly. Close your browser and reload the page; your note is retrieved from the data store and displayed in the text area instead of the default directions.

5362.jpg

Notepad form at start-up.

5349.jpg

Data entry saved after page reloaded.

Advanced data storage

Current browsers support the basic key/value pair methods of the localStorage API. There is also an advanced specification called the Indexed Database API that permanently stores large amounts of data in a transactional database. This specification has replaced the older Web SQL Database proposal originally created by the Web Applications Working Group.

7872.jpg For the current status of the Indexed Database API specification, visit: http://www.w3.org/TR/IndexedDB/.

The Indexed Database API exposes what’s called an object store, which shares many concepts with a SQL database. For example, object stores have databases with records. Each record has a set number of fields, and each field has a specific datatype, defined when the database is created. You can select a subset of records, and then enumerate them with a cursor. Changes to the object store are handled within transactions.

The primary difference between IndexedDB and Web SQL Database is that the IndexedDB object store has no structured query language; for example, you don’t construct a statement such as SELECT * from CUSTOMER. Instead, you use programming methods to open a cursor, enumerate and filter records, and use accessor methods to obtain field values.

The IndexedDB API is nearing the end of the W3’s Candidate Recommendation status at the time of this writing. This means the IndexedDB API is likely to reach recommendation status and be adopted as a standard. The current version of nearly every major browser support IndexedDB, with the lone exception being Safari. Additionally, IndexedDB is only available on sites with http or https URL schemes which means IndexedDB data can only be accessed over a web server. We strongly recommend that you research the current state of each browser’s support for advanced data storage before you develop an application with this technology.

Application caching

In the previous section of this lesson, you learned about HTML5 storage using named key/value pairs and briefly looked at IndexedDB to save data. You will likely use these techniques for the majority of online storage tasks. You can also take an application offline by saving its stylesheets, scripts, and graphic elements with application caching.

The cache manifest file

The cache manifest is a simple text file specified in the <HTML> tag of a web page that lists the resources that should be cached for offline use. Resource files can include HTML, CSS, JavaScript files, and other resources, such as images and video. The following line of code is an example.

<html manifest="http://www.example.com/cache.manifest">

You need to include the manifest attribute on every page of your web application you want cached for offline storage. The browser will not cache a page for offline use without this attribute, unless the page is explicitly listed in the manifest file. In other words, any page the user navigates to that includes a manifest attribute will be implicitly added to the application cache, thus avoiding the need to list every page in your manifest.

The manifest attribute can point to an absolute URL (as in the example above), or to a relative path; keep in mind that an absolute URL must be stored in the same server as the web application. A manifest file can have any file extension, but it needs to be served with the correct MIME-Type.

Cache manifest structure

Here is an example of a simple manifest file:

CACHE MANIFEST

stylesheet.css

logo.png

main.js

index.html

Here is an example of a complete manifest file:

CACHE MANIFEST

# 2011-06-18:v2

# Explicitly cached 'master entries'.

CACHE:

/favicon.ico

index.php

stylesheet.css

fonts/MoolBoran.ttf

images/logo.png

scripts/main.js

# Resources that require the user to be online.

NETWORK:

login.php

/api

http://api.twitter.com

# files to serve if not accessible

FALLBACK:

/index.php /index.html

images/large/ images/offline.jpg

*.html /offline.html

There are three sections in a manifest file:

1 CACHE—the default section; lists files to be stored offline.

2 NETWORK—identifies files to always retrieve from the network. You can use wildcards (*).

3 FALLBACK—optional section that defines files when a resource is inaccessible. You can use wildcards (*).

7878.jpg Every page pointing to the manifest is automatically added to the cache as a MASTER entry and behaves as though it were listed in the CACHE section.

Updating the cache

An offline application remains cached until one of the following happens:

  • The user clears their browser’s data storage for your site.
  • The manifest file is modified.
  • The app cache is programmatically updated.

Lines starting with the pound symbol (#) are comment lines, but they can also serve another purpose. An application’s cache is updated only when its manifest file changes. For example, if you edit an image resource or change a JavaScript function, those changes will not be re-cached. Creating a comment line with a generated version number or timestamp is one way to ensure the cache is updated and users have the latest version of your application. You can also programmatically update the cache once a new version is ready as discussed in The Application Cache Object section.

7887.jpg Updating a file listed in the manifest does not re-cache that resource. You must change the manifest file before the application re-caches all files.

The object

The window.applicationCache object is your programmatic access to the browser’s cache. You can use this object’s status property to check the current state of the cache:

var appCache = window.applicationCache;

switch (appCache.status) {

case appCache.UNCACHED: // UNCACHED = 0

return 'UNCACHED';

break;

case appCache.IDLE: // IDLE = 1

return 'IDLE';

break;

case appCache.CHECKING: // CHECKING = 2

return 'CHECKING';

break;

case appCache.DOWNLOADING: // DOWNLOADING = 3

return 'DOWNLOADING';

break;

case appCache.UPDATEREADY:   // UPDATEREADY = 5

return 'UPDATEREADY';

break;

case appCache.OBSOLETE: // OBSOLETE = 5

return 'OBSOLETE';

break;

default:

return 'CACHE STATUS UNKNOWN';

break;

};

To programmatically update the cache, first call the applicationCache.update function, which updates the user’s cache when the manifest file changes. The next step is to call the applicationCache.swapCache function when the applicationCache.status is in UPDATEREADY state to swap the old cache for the new one. The most efficient way to update users to the newest version of your application is to set a listener on page load to monitor the UPDATEREADY event:

// Check if a new cache is available on page load.

var appCache = window.applicationCache;

window.addEventListener('load', function(e) {

appCache.addEventListener('updateready', function(e) {

if (appCache.status == appCache.UPDATEREADY) {

// Browser has downloaded a new app cache.

// Swap it in and reload the page to get the new files.

appCache.swapCache();

window.location.reload();

} else {

// Manifest hasn't changed.

}

}, false);

}, false);

If the manifest file or a resource specified in it fails to download, the entire update fails and the browser continues to use the current application cache.

Bringing it all together

The source files that accompany this lesson contain an offline application, its manifest file, and its resource files. The notepad_example_offline.html page located in the offline folder inside the HTML5_14lessons folder contains a URL placeholder for your actual domain name. The following line of code shows the manifest file declaration.

<html manifest="http://www.[your_website].com/offline/cache.manifest">

1 Change the text [your_website] in the html element’s manifest attribute to your actual domain name.

2 Copy the offline folder onto your web server.

7897.jpg Contact your web service provider before you run the application to ensure text/cache-manifest is added to your MIME types or .htaccess configuration file.

The first time you run the application, it will download all files listed in the manifest. When you run the application again, it will check whether the manifest has changed; if so, the application will update all downloaded files.

Self study

The advanced data storage in HTML5 is still being implemented by the browser vendors. See http://www.w3.org/TR/IndexedDB/ for information about IndexedDB Storage and http://www.w3.org/TR/webstorage/ for the latest web storage specifications.

Review

Questions

1 True or False: The manifest attribute only needs to be added to the home page of an application.

2 Can data stored by one domain be accessed from another domain?

3 How are cached files updated?

Answers

1 False. Every page of your web application needs a manifest attribute that points to the cache manifest file unless that page is explicitly listed in the manifest file.

2 No. Data is accessible only from the originating domain. It is possible to share data between applications from the same domain, but no outside application or website can access them.

3 The manifest file must be changed before the application will re-cache all files. Changing a comment line with a generated version number or timestamp is one way to ensure the cache gets updated. You can also programmatically update the cache.

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

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