Offline Web Application
Background
The discussions run wild on the Internet on whether to write native apps for each mobile platform or only build one web app that works on all. By building a native app you get more control from the device. You get cleared for access to gyro, gps, camera and so on while you accept to install the app. While with a web application you need to ask permission every time you use it and the support for hardware is often more stable if you run native. But you get access to more and more even from the browser. And in this post I'm going to show you how you can create a web page that can be run offline, even if it has a remote data source.
Technologies
Apart from the obvious HTML and JavaScript you need something called appcache in order to tell the browser to save some files locally. Then you also need to access the indexedDB in order to store data from your remote data source.
First let's take a look at the index.html file
// index.html
Here you can see that I have included the cache.manifest file. This file contains the files that the browser should save for offline use. Then you can see that I have included a indexeddb.shim.min.js. This is so that I have a fallback for browsers that does not support indexeddb. I really recommend using this because there is still some differences in support when it comes to browser data storage solutions. But from what I can read out there this should get you covered in most browsers.
Then I have an application.js file which contain my javascript code.
Application Cache
Let's have a look in the manifest file for the Application Cache
// cache.manifest
CACHE MANIFEST
NETWORK:
*
CACHE:
application.js
FALLBACK:
#not_available_offline.html
The * under NETWORK means that I cache all urls that I need for the site to run, but if I am online the online sources will be used. Then I explicitly cache application.js so that I always use the cached version. I guess I do not need to do that, but I'm just experimenting a bit here and showing you the options. So bare with me =)
At the end there is also a fallback if the browser does not support appcache
IndexedDB and javascript
Now take a look at the JavaScript. Everything starts at the databaseOpen function. It opens the indxedDB, checks if an update is needed and calls the function getSiteObject.
document.addEventListener("DOMContentLoaded", function(){
if ("indexedDB" in window) {
//alert("YES!!! I CAN DO IT!!! WOOT!!!");
} else {
//alert("I has a sad.");
}
// General functions
ajaxRequest = function() {
var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"]; //activeX versions to check for in IE
if (window.ActiveXObject) { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
for (var i=0; i
As you can see in the render function at the bottom we start out by reading data from the indexedDB data source and then we try to access our server to fetch some updated data. If that fails we still have our cached version and if we get the new data then the view and the data source is updated.
In this sample I only use a random number generator as a data source. Here is the code for that one.
// ajax.php
And you might also want to update your .htaccess file with the following line:
// .htaccess
AddType text/cache-manifest .manifest
Current thoughts
The reason why I went back to this old code is because I'm trying to rewrite a website I have, in order to make it more mobile friendly. But I struggle a bit, because I do not only want to rely on this solution. I also want to site available without any app cache and JavaScript updating the interface. I need the page to load with data but not if the user have data in their app cache. But the server does not know that without talking to the client first. I'm not sure how well google manages data that are loaded dynamically. Probably okej but I do not want to take any chanses.
I do not want a complete copy of my database locally, but I still want enough data so that I can use the site offline. One of the major benefits is that I can remove a lot of load from the server with this method. I'm thinking about storing the same data structure in the SESSION variable in php, as a fallback from the app cache.
There are a lot of questions here and I'm sure most of them will turn out to be easier than I thought, so I should just start coding and stop procastenating...
- mobile, application cache, indexeddb, software