header. Simple cache entries like those shown above go in a “CACHE:” section, which
is the default section. The other two sections begin with the headers “NETWORK:”
and “FALLBACK:”. (A manifest can have any number of sections and can switch back
and forth between sections as needed.)
The “NETWORK:” section specifies URLs that must never be cached and should al-
ways be retrieved from the network. You might list server-side scripts here, for example.
The URLs in a “NETWORK:” section are actually URL prefixes. A resource whose
URL begins with any one of these prefixes will be loaded from the network. If the
browser is offline, that attempt will fail, of course. The “NETWORK:” section allows
a wildcard URL “*”. If you use this wildcard, the browser will attempt to load any
resource not mentioned in the manifest from the network. This effectively defeats the
rule that says that cached applications must list all their resources in the manifest.
The manifest entries in the “FALLBACK:” section include two URLs on each line. The
second URL is loaded and is stored in the cache. The first URL is a prefix. URLs
matching this prefix will not be cached, but they will be loaded from the network when
possible. If the attempt to load such a URL fails, the cached resource specified by the
second URL will be used instead. Imagine a web application that includes a number of
video tutorials. Because these videos are very large, they are not appropriate to cache
locally. For offline use, a manifest file could fall back on a text-based help file instead.
Here is a more complicated cache manifest:
CACHE MANIFEST
CACHE:
myapp.html
myapp.css
myapp.js
FALLBACK:
videos/ offline_help.html
NETWORK:
cgi/
20.4.2  Cache Updates
When you load a web application that has been cached, all of its files come directly
from the cache. If the browser is online, it will also asynchronously check to see if the
manifest file has changed. If it has changed, the new manifest file, and all the files it
references, are downloaded and reinstalled in the application cache. Note that the
browser does not check to see whether any of the cached files have changed: only the
manifest. If you modify a cached JavaScript file, for example, and want sites that have
cached your web app to update their cache, you must update the manifest. Since the
list of files required by your app has not changed, the easiest way to do this is by
updating a version number:
20.4  Application Storage and Offline Webapps | 603
Client-Side
JavaScript
Pdf link to email - insert, remove PDF links in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Free C# example code is offered for users to edit PDF document hyperlink (url), like inserting and deleting
add hyperlink to pdf in preview; add hyperlinks pdf file
Pdf link to email - VB.NET PDF url edit library: insert, remove PDF links in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Help to Insert a Hyperlink to Specified PDF Document Page
add hyperlink to pdf; adding links to pdf in preview
CACHE MANIFEST
# MyApp version 1 (change this number to make browsers redownload the files)
MyApp.html
MyApp.js
Similarly, if you want a web app to uninstall itself from the application cache, you
should delete the manifest file on the server, so that requests for it return an HTTP 404
Not Found error, and modify your HTML file or files so that they no longer link to the
manifest.
Note that the browser checks the manifest and updates the cache asynchronously, after
(or while) loading the cached copy of an application. For simple web apps, this means
that after you update the manifest, the user must load the application twice before he
sees the new version: the first load loads the old version from the cache and then updates
the cache. Then the second load loads the new version from the cache.
The browser fires a number of events during the cache update process, and you can
register handlers to track the process and provide feedback to the user. For example:
applicationCache.onupdateready = function() {
var reload = confirm("A new version of this application is available\n" +
"and will be used the next time you reload.\n" +
"Do you want to reload now?");
if (reload) location.reload();                         
}
Note that this event handler is registered on the ApplicationCache object that is the
value of the 
applicationCache
property of the Window. Browsers that support an ap-
plication cache will define this property. In addition to the updateready event shown
above, there are seven other application cache events you can monitor. Example 20-4
shows simple handlers that display messages to the user informing them of the progress
of the cache update and of the current cache status.
Example 20-4. Handling application cache events
// The event handlers below all use this function to display status messages.
// Since the handlers all display status messages this way, they return false
// to cancel the event and prevent the browser from displaying its own status.
function status(msg) {
// Display the message in the document element with id "statusline"
document.getElementById("statusline").innerHTML = msg;
console.log(msg);  // And also in the console for debugging
}
// Each time the application is loaded, it checks its manifest file.
// The checking event is always fired first when this process begins.
window.applicationCache.onchecking = function() {
status("Checking for a new version.");
return false;
};
// If the manifest file has not changed, and the app is already cached,
// the noupdate event is fired and the process ends.
window.applicationCache.onnoupdate = function() {
604 | Chapter 20: Client-Side Storage
RasterEdge.com General FAQs for Products
copy and email the secure download link to the assistance, please contact us via email (support@rasteredge & profession imaging controls, PDF document, image to
clickable links in pdf from word; pdf link to email
RasterEdge Product Licensing Discount
s). After confirming the informations provided, we will send you an email that contains price(s) at a discount and the online order link for new licensing.
adding hyperlinks to pdf; pdf email link
status("This version is up-to-date.")
return false;
};
// If the application is not already cached, or if the manifest has changed,
// the browser downloads and caches everything listed in the manifest.
// The downloading event signals the start of this download process.
window.applicationCache.ondownloading = function() {
status("Downloading new version");
window.progresscount = 0;  // Used in the progress handler below
return false;
};
// progress events are fired periodically during the downloading process,
// typically once for each file downloaded. 
window.applicationCache.onprogress = function(e) {
// The event object should be a progress event (like those used by XHR2)
// that allows us to compute a completion percentage, but if not,
// we keep count of how many times we've been called.
var progress = "";
if (e && e.lengthComputable) // Progress event: compute percentage
progress = " " + Math.round(100*e.loaded/e.total) + "%"
else                         // Otherwise report # of times called
progress = " (" + ++progresscount + ")"
status("Downloading new version" + progress);
return false;
};
// The first time an application is downloaded into the cache, the browser
// fires the cached event when the download is complete.
window.applicationCache.oncached = function() {
status("This application is now cached locally");
return false;
};
// When an already-cached application is updated, and the download is complete
// the browser fires "updateready". Note that the user will still be seeing
// the old version of the application when this event arrives.
window.applicationCache.onupdateready = function() {
status("A new version has been downloaded.  Reload to run it");
return false;
};
// If the browser is offline and the manifest cannot be checked, an "error"
// event is fired. This also happens if an uncached application references
// a manifest file that does not exist
window.applicationCache.onerror = function() {
status("Couldn't load manifest or cache application");
return false;
};
// If a cached application references a manifest file that does not exist,
// an obsolete event is fired and the application is removed from the cache.
// Subsequent loads are done from the network rather than from the cache.
window.applicationCache.onobsolete = function() {
20.4  Application Storage and Offline Webapps | 605
Client-Side
JavaScript
RasterEdge Product Renewal and Update
4. Order email. Our support team will send you the purchase link. HTML5 Viewer for .NET; XDoc.Windows Viewer for .NET; XDoc.Converter for .NET; XDoc.PDF for .NET;
add hyperlinks to pdf online; adding hyperlinks to pdf files
VB.NET Create PDF from PowerPoint Library to convert pptx, ppt to
Link: Edit URL. Bookmark: Edit Bookmark. Metadata: Edit, Delete Metadata. Form Process. Create PDF file from PowerPoint free online without email.
pdf link to attached file; adding links to pdf document
status("This application is no longer cached. " + 
"Reload to get the latest version from the network.");
return false;
};
Each time an HTML file with a 
manifest
attribute is loaded, the browser fires a checking
event and loads the manifest file from the network. The events that follow the checking
event are different in different situations:
No update available
If the application is already in the cache, and the manifest file has not changed, the
browser fires a noupdate event.
Update available
If an application is cached, and its manifest file has changed, the browser fires a
downloading event and begins downloading and caching all the files listed in the
manifest. As this download occurs, it fires progress events. And when the download
is complete, it fires an updateready event.
First load of new application
If the application is not yet in the cache, downloading and progress events are fired
as they are for the cache update case above. Once this initial download is complete,
however, the browser fires a cached event rather than an updateready event.
Browser is offline
If the browser is offline, it cannot check the manifest and it fires an error event.
This also happens when an application that has not yet been cached refers to a
manifest file that does not exist.
Manifest not found
If the browser is online and the application is already cached, but the manifest file
returns a 404 Not Found error, it fires an obsolete event and removes the applica-
tion from the cache.
Note that all of these events are cancelable. The handlers in Example 20-4 returns
false
to cancel the default action associated with the events. This prevents browsers
from displaying their own cache status messages. (At the time of this writing, browsers
do not display any such messages.)
As  an  alternative  to  the  event  handlers,  an  application  can  also  use  the
applicationCache.status
property to determine the cache status. There are six possible
values for this property:
ApplicationCache.UNCACHED (0)
This application does not have a 
manifest
attribute: it is not cached.
ApplicationCache.IDLE (1)
The manifest has been checked and this application is cached and up to date.
ApplicationCache.CHECKING (2)
The browser is checking the manifest file.
606 | Chapter 20: Client-Side Storage
VB.NET Create PDF from Word Library to convert docx, doc to PDF in
Link: Edit URL. Bookmark: Edit Bookmark. Metadata: Edit, Delete Metadata. Form Process. Free online Word to PDF converter without email.
add hyperlink pdf document; add a link to a pdf file
VB.NET Create PDF from Excel Library to convert xlsx, xls to PDF
Link: Edit URL. Bookmark: Edit Bookmark. Metadata: Edit, Delete Metadata. Form Process. Convert Excel to PDF document free online without email.
add url to pdf; add links to pdf document
ApplicationCache.DOWNLOADING (3)
The browser is downloading and caching files listed in the manifest.
ApplicationCache.UPDATEREADY (4)
A new version of the application has been downloaded and cached.
ApplicationCache.OBSOLETE (5)
The manifest no longer exists and the cache will be deleted.
The ApplicationCache object also defines two methods. 
update()
explicitly invokes the
cache update algorithm to check for a new version of the application. This causes the
browser to run through the same manifest check (and fire the same events) as it does
when an application is first loaded.
The 
swapCache()
method is trickier. Recall that when the browser downloads and ca-
ches an updated version of an application, the user is still running the out-of-date ver-
sion. If the user reloads the app, she’ll see the new version. But if the user does not
reload, the old version must still run correctly. And notice that the old version may still
be loading resources from the cache: it might be using XMLHttpRequest to request
files, for example, and these requests must be satisfied by files in the old version of the
cache. Therefore, the browser must generally keep the old version of the cache until
the user reloads the application.
The 
swapCache()
method tells the browser that it can discard the old cache and satisfy
any future requests from the new cache. Note that this does not reload the application:
HTML files, images, scripts, and so on that have already been loaded are not changed.
But any future requests will come from the new version of the cache. This can cause
version-skew issues and is not generally a good idea unless your app is carefully de-
signed to allow it. Imagine, for example, an application that does nothing but display
a splash screen of some sort while the browser is checking the manifest. When it sees
the noupdate event, it goes ahead and loads the application’s start page. If it sees a
downloading event, it displays appropriate progress feedback while the cache is upda-
ted. And when it gets an updateready event, it calls 
swapCache()
and then loads the
updated start page from the latest version of the cache.
Note that it only makes sense to call 
swapCache()
when the 
status
property has the
value 
ApplicationCache.UPDATEREADY
or 
ApplicationCache.OBSOLETE
 (Calling
swapCache()
when the 
status
is 
OBSOLETE
discards the obsolete cache immediately, and
satisfies all future requests via the network.) If you call 
swapCache()
when 
status
has
any other value, it will throw an exception.
20.4.3  Offline Web Applications
An offline web application is one that installs itself in the application cache so that it
is always available, even when the browser is offline. For the simplest cases—things
like clocks and fractal generators—this is all a web app needs to do to become an offline
web app. But most nontrivial web apps need to upload data to the server as well: even
simple game apps might want to upload a user’s high score to the server. Apps that
20.4  Application Storage and Offline Webapps | 607
Client-Side
JavaScript
VB.NET PDF Convert to Word SDK: Convert PDF to Word library in vb.
Create editable Word file online without email. Supports transfer from password protected PDF. VB.NET class source code for .NET framework.
chrome pdf from link; add hyperlink to pdf in
C# PDF Convert to Word SDK: Convert PDF to Word library in C#.net
and .docx. Create editable Word file online without email. Password protected PDF file can be printed to Word for mail merge. C# source
add link to pdf acrobat; add page number to pdf hyperlink
need to upload data to a server can be offline web apps if they use 
localStorage
to store
application data, and then upload it when an Internet connection is available. Syn-
chronizing data between local storage and the server can be the trickiest part of con-
verting a web app for offline use, especially when the user might be accessing the data
from more than one device.
In order to work offline, a web application needs to be able to tell whether it is offline
or online and needs to know when the state of the Internet connection changes. To
check whether the browser is online, a web app can use the 
navigator.onLine
property.
And to detect changes in the connection state, it can register handlers for online and
offline events on the Window object.
This chapter concludes with a simple offline web app that demonstrates these techni-
ques. The app is called PermaNote—it is a simple note application that saves the user’s
text to 
localStorage
and by uploading it to the server whenever an Internet connection
is available.
1
PermaNote only allows the user to edit a single note, and it ignores au-
thorization and authentication issues—it assumes the server has some way of distin-
guishing one user from another, but does not include any kind of login screen. The
PermaNote implementation consists of three files. Example 20-5 is the cache manifest.
It lists the other two files and specifies that the URL “note” should not be cached: that
is the URL we use to read and write the note to the server.
Example 20-5. permanote.appcache
CACHE MANIFEST
# PermaNote v8
permanote.html
permanote.js
NETWORK:
note
Example 20-6 is the second PermaNote file: it is an HTML file that defines a very simple
editor UI. It displays a 
<textarea>
element with a row of buttons across the top and a
status line for messages along the bottom. Notice that the 
<html>
tag has a 
manifest
attribute.
Example 20-6. permanote.html
<!DOCTYPE HTML>
<html manifest="permanote.appcache">
<head>
<title>PermaNote Editor</title>
<script src="permanote.js"></script>
<style>
#editor { width: 100%; height: 250px; }
#statusline { width: 100%; }
</style>
1.This example was loosely inspired by Halfnote, by Aaron Boodman. Halfnote was one of the first offline
web apps.
608 | Chapter 20: Client-Side Storage
C# Create PDF from Excel Library to convert xlsx, xls to PDF in C#
Export PDF from Excel with cell border or no border. Free online Excel to PDF converter without email. Quick integrate online C# source code into .NET class.
change link in pdf; add links to pdf acrobat
C# Create PDF from PowerPoint Library to convert pptx, ppt to PDF
application. Free online PowerPoint to PDF converter without email. C# source code is provided for .NET WinForms class. Evaluation
add links to pdf file; add link to pdf
</head>
<body>
<div id="toolbar">
<button id="savebutton" onclick="save()">Save</button>
<button onclick="sync()">Sync Note</button>
<button onclick="applicationCache.update()">Update Application</button>
</div>
<textarea id="editor"></textarea>
<div id="statusline"></div>
</body>
</html>
Finally, Example 20-7 lists the JavaScript code that makes the PermaNote web appli-
cation work. It defines a 
status()
function for displaying messages on the status line,
save()
function for saving the current version of the note to the server, and a 
sync()
function for making sure that the server’s copy and the local copy are in sync. The
save()
and 
sync()
functions use scripted HTTP techniques from Chapter 18. (Inter-
estingly, the 
save()
function uses the HTTP “PUT” method instead of the much more
common POST method.)
In addition to these three basic functions, Example 20-7 defines event handlers. In order
to keep the local copy and the server’s copy of the note synchronized, the app requires
quite a few event handlers:
onload
Try to sync with the server, in case there is a newer version of the note there, and
once synchronization is complete, enable the editor window.
The 
save()
and 
sync()
functions make HTTP requests, and they register an onload
handler on the XMLHttpRequest object to be notified when the upload or down-
load is complete.
onbeforeunload
Save the current version of the note to the server if it has not been uploaded.
oninput
Whenever the text in the 
<textarea>
changes, save it in 
localStorage
, and start a
timer. If the user stops editing for 5 seconds, save the note to the server.
onoffline
When the browser goes offline, display a message in the status line.
ononline
When the browser comes back online, synchronize with the server, checking for a
newer version, and saving the current version.
onupdateready
If a new version of the cached application is ready, display a message in the status
line to let the user know.
onnoupdate
If the application cache has not changed, let the user know that he or she is running
the current version.
20.4  Application Storage and Offline Webapps | 609
Client-Side
JavaScript
With that overview of PermaNote’s event-driven logic, here is Example 20-7.
Example 20-7. permanote.js
// Some variables we need throughout
var editor, statusline, savebutton, idletimer;
// The first time the application loads
window.onload = function() {
// Initialize local storage if this is the first time
if (localStorage.note == null) localStorage.note = "";
if (localStorage.lastModified == null) localStorage.lastModified = 0;
if (localStorage.lastSaved == null) localStorage.lastSaved = 0;
// Find the elements that are the editor UI. Initialize global variables.
editor = document.getElementById("editor");
statusline = document.getElementById("statusline");
savebutton = document.getElementById("savebutton");
editor.value = localStorage.note; // Initialize editor with saved note
editor.disabled = true;           // But don't allow editing until we sync
// Whenever there is input in the textarea
editor.addEventListener("input",
function (e) {
// Save the new value in localStorage
localStorage.note = editor.value;
localStorage.lastModified = Date.now();
// Reset the idle timer
if (idletimer) clearTimeout(idletimer);
idletimer = setTimeout(save, 5000);
// Enable the save button
savebutton.disabled = false;
},
false);
// Each time the application loads, try to sync up with the server
sync();
};
// Save to the server before navigating away from the page
window.onbeforeunload = function() {
if (localStorage.lastModified > localStorage.lastSaved)
save();
};
// If we go offline, let the user know
window.onoffline = function() { status("Offline"); }
// When we come online again, sync up.
window.ononline = function() { sync(); };
// Notify the user if there is a new version of this application available.
// We could also force a reload here with location.reload()
window.applicationCache.onupdateready = function() {
status("A new version of this application is available. Reload to run it");
610 | Chapter 20: Client-Side Storage
};
// Also let the user know if there is not a new version available.
window.applicationCache.onnoupdate = function() {
status("You are running the latest version of the application.");
};
// A function to display a status message in the status line
function status(msg) { statusline.innerHTML = msg; }
// Upload the note text to the server (if we're online).
// Will be automatically called after 5 seconds of inactivity whenever
// the note has been modified.
function save() {
if (idletimer) clearTimeout(idletimer);
idletimer = null;
if (navigator.onLine) {
var xhr = new XMLHttpRequest();
xhr.open("PUT", "/note");
xhr.send(editor.value);
xhr.onload = function() {
localStorage.lastSaved = Date.now();
savebutton.disabled = true;
};
}
}
// Check for a new version of the note on the server. If a newer
// version is not found, save the current version to the server.
function sync() {
if (navigator.onLine) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/note");
xhr.send();
xhr.onload = function() {
var remoteModTime = 0;
if (xhr.status == 200) {
var remoteModTime = xhr.getResponseHeader("Last-Modified");
remoteModTime = new Date(remoteModTime).getTime();
}
if (remoteModTime > localStorage.lastModified) {
status("Newer note found on server.");
var useit =
confirm("There is a newer version of the note\n" +
"on the server. Click Ok to use that version\n"+
"or click Cancel to continue editing this\n"+
"version and overwrite the server");
var now = Date.now();
if (useit) {
editor.value = localStorage.note = xhr.responseText;
localStorage.lastSaved = now;
status("Newest version downloaded.");
}
else 
20.4  Application Storage and Offline Webapps | 611
Client-Side
JavaScript
status("Ignoring newer version of the note.");
localStorage.lastModified = now;
}
else
status("You are editing the current version of the note.");
if (localStorage.lastModified > localStorage.lastSaved) {
save();
}
editor.disabled = false;  // Re-enable the editor
editor.focus();           // And put cursor in it
}
}
else { // If we are currently offline, we can't sync
status("Can't sync while offline");
editor.disabled = false;
editor.focus();
}
}
612 | Chapter 20: Client-Side Storage
Documents you may be interested
Documents you may be interested