To make applications that can work in a completely autonomous mode, we need to get acquainted with the following technologies: HTML5 Application Cache, Web Storage and WebSQL.
I have already published introductory articles on
Web Storage and
HTML5 Application Cache . I recommend them to read if you are not familiar with the basic concepts. This article will revise these technologies, including WebSQL, and describe the options for sharing them effectively. All these technologies are supported by the desktop version of Opera 11.10 browser, Opera Mobile 11, WebKit browsers (in iOS and Google Android).
Note: All the examples described below are available in this archive . You can download the archive and watch examples while reading the article (naturally, being offline). |
Why do we need an “offline mode”?
Currently, web pages are not just text. The Internet is becoming more widespread, and web applications, respectively, are also becoming more and more complex and sophisticated. And our dependence on them only grows. We can see more and more examples of web applications successfully replacing traditional desktop applications, whose main advantage has always been their ability to safely work offline. To give the same opportunity to web applications did not allow the lack of the necessary technologies and tools.
But everything changes when they come ...But now this is not a problem! With the advent of technologies such as HTML5 Application Cache, Web Storage, and WebSQL, we finally got a way to make web applications work offline:
- Application Cache allows you to keep a copy of HTML, CSS and other elements of our web application offline, which will be used when the network is unavailable.
- Web Storage is based on storage mechanisms like cookies, representing a more flexible and more powerful implementation.
- WebSQL implements a full-sized SQL database inside your browser that can store copies of web application data for offline use, allowing users to continue working with data even if they lose connection to the network. Data is synchronized with the server when it is next connected to the network.
There are many reasons for the loss of connection to the network: power failure, problems with network equipment, the missing (or weak) signal in the case of work through a cell phone. As developers, we want to be sure that even in such situations our web applications will work correctly (at least within reasonable limits).
Cache: loaded and in the absence of the network
In general, if we are not online, we will get an error when loading or reloading pages on the site. The first thing to do is make sure that our users can see the pages and work with the web application even when there is no connection, i.e. all images, CSS, JavaScript and the HTML page itself must be loaded correctly in this mode.
This is achieved through the use of technology Application Cache (also called AppCache). To use it, you first need to declare a manifest file in which to specify the names of the files that the application needs to work offline.
Sample
demo.manifest file:
CACHE MANIFEST CACHE: logo.png style.css script.js jquery.js index.htm
Whatever links this manifest file contains, the corresponding content is placed in the cache, and subsequently this content will already be accessed. Declaring a manifest file is very simple - you need to use the
manifest attribute of the
<html> element:
<html manifest="demo.manifest">
All files declared in this file will be placed in the cache of your browser. Even if a person is offline and tries to load the page, all the resources listed in this file will be loaded by the browser.
More information about this can be found in the article about
HTML5 Application Cache .
What about the data?
AppCache solves the problem of the availability of some elements of the site offline, but we may want to store some amount of user data or, for example, its recent search queries. In another case, you may want to store more structured data. In any case, Web Storage and WebSQL will be the best solution.
')
We use Web Storage
Web Storage is perfect for storing small amounts of information, rather than huge tables with data, which we will briefly discuss in this article, consider examples. For more information, you can find in a separate
article on Web Storage .
There are many places where frequent power outages are common (“Chubais, hello! :)”, from a translator. The user has to sit and wait for him to continue his work on the Internet until he turns on the electricity. Imagine if someone was in a similar situation filling out a multi-page form on a website, typing a large article for a blog or an important email. During a power outage (or batteries will sit down), the user will lose all this data. Wouldn't it be better if, after logging in to the network, all unsaved records will be available to him, with which he will continue working?
Let's see what can be done on the page containing the plain text field
<textarea> ? The page should save everything that we type into the local storage every few seconds, and in case of its reloading or closing, the page should load the last text stored in the field.
Suppose our page contains a
<textarea> field with the
id “draft”:
... <textarea id="draft" rows="10" cols="30"></textarea> ...
Let's write a simple function that will save the contents of
<textarea> to the local storage:
function saveMessage(){ var message = document.getElementById("draft"); localStorage.setItem("message", message.value) }
Set the save interval to half a second:
setInterval(saveMessage, 500);
Note: here we used setInterval () for simplicity to save a message to the local storage every half second. (You could improve this procedure, for example, saving the contents of a text field only if the user entered something into it). |
You also need to make sure that each time the page is opened or reloaded, the last saved content from the local storage (
localStorage ) is loaded into the text field:
window.addEventListener("DOMContentLoaded", loadMessage, false); function loadMessage() { var textbox = document.getElementById("draft"); var message = localStorage.getItem("message"); if (!message) { textbox.value = ""; }else { textbox.value = message; } }
See an example of
working with Web Storage . It is generally chic
If you need to save locally small pieces of information.
We work offline
To go offline, you need to activate it (in Opera browser: “Menu” → “Settings” → “Work offline” or “File” → “Work offline”). The
navigator.onLine property is
false if the browser is offline, otherwise it is
true . However, in many cases it would be better to use events. When the user switches to offline mode, an
offline event is triggered; when it switches back, it is correspondingly
online . You can use this to display a small message about going offline.
Something like this will turn out:
... window.addEventListener( "offline", function(){showWarningDiv("on")}, false); window.addEventListener( "online", function(){showWarningDiv("off")}, false); ... function showWarningDiv(status){ var warningdiv = document.getElementById("warning"); if (status == "on"){ warningdiv.innerHTML = "<p style=\"padding:3px;\">Right now you are in offline mode. This message is saved and will be sent to the server the next time you are online.</p>"; } else { warningdiv.innerHTML = ""; } }
Note: currently, offline support is only available in Opera and Firefox. |
It makes sense to ensure that forms do not attempt to send data while the user is offline. To check this, we can do this:
... window.addEventListener( "submit", submitForm, false); ... function submitForm(){ saveMessage(); if (!navigator.onLine){ return false; } }
When submitting form data, a
submit event is triggered, which calls the
submitForm () function. This function will first save the message to the local storage, then, if the user is offline, the data will not be sent anywhere.
You can improve this example so that it saves a copy to the server every few seconds so that it is available there in case the user accidentally deletes the data from himself. This is especially important in those cases of work, for example, with confidential information: you say, you want your credit card information to be stored only in your local storage.
See also a
more advanced example that uses
sessionStorage to store information. If you do not close the page (even if it is reloaded), the text entered in the text field will remain there. The page will also send the contents of this field to the server every few seconds and, accordingly, update the last save time. This approach can be used in blogging engines and email services to periodically save the “drafts”, which will allow you to continue working in case of problems with the connection.
WebSQL: another “service” offline
Web Storage is great for storing small amounts of information, but what if we want to store a whole database? How about that the web application could do various inquiries to a database, search in it?
Here, Web Storage will no longer allow to turn around - you need something more reliable. Namely - WebSQL. WebSQL is a local SQLite database in which you can store your data using a combination of Javascript and SQL.
Work with WebSQL-databases
First of all, you need to make sure that the browser supports WebSQL? This can be done through the
window.openDatabase property:
if (window.openDatabase){
Creating and opening a database
You can create and open a database using the
openDatabase command, as follows:
var db = openDatabase("food_db", "1.0", "Web SQL Storage Demo Database", 1*1024*1024);
We have just created a
food_db version 1.0 database, with a description of
“Web SQL Storage Demo Database” , 1 MB in size. The variable
db is a pointer to a database object, which we will continue to use.
Note: database size is set in bytes. Therefore, we determined the size in the format 1 * 1024 * 1024, which is 1 MB. If you need to set the size, for example, 4 MB, you should specify the value 4 * 1024 * 1024, respectively. |
Work with database
We created and opened a database. Now you can perform various operations on it using SQL commands. We will perform operations by calling the
transaction () function of the database object (in our case, this is
db ). Its call returns an object as a pointer, over which we will execute various commands using
executeSQL () . The syntax of this command is as follows:
executeSql(sqlStatement, arguments, callback, errorCallback);
Of the parameters, only
sqlStatement is required, the rest are optional.
So, for example, if we want to create a table, we will need to write the following:
... db.transaction( function(t){
This code will create a
cal_list table (if it did not exist) with the fields
food_name ,
calories, and
servings .
Adding records to the table
Making requests to add records to a table is a simple task for WebSQL. Consider an example:
var food_name = "pizza"; var amount_of_calories = 320; var serving_size = "one slice"; db.transaction( function(t){ t.executeSql("INSERT INTO cal_list VALUES (?, ?, ?)", [food_name, amount_of_calories, serving_size]); } );
The first question mark escapes the
food_name parameter, the second, the
amount_of_calories parameter , and the third,
serving_size . This code adds an entry to the
cal_list table with the values:
pizza ,
320 and
one slice corresponding columns.
Perform another request - to receive data:
var min_cal_amount = 300; ... t.executeSql("SELECT * FROM cal_list WHERE calories > ?", [min_cal_amount]);
This code will execute a query to fetch all rows with a
calories greater than 300: the question mark escapes the
min_cal_amount variable.
Processing query results
Well, we have created a database with tables in which we have written data, now we want to make a query and display the results. Usually, we get a bunch of results for one SQL query and we need to somehow process these results in order to display them in a table or some other structured form on the page. The third parameter of the executeSQL () function determines the success of the query execution. Below is an example of processing the results:
var list = document.getElementById("thelist"); var food; var min_cal_amount = 400; var serving_size; db.transaction( function(t){ t.executeSql("SELECT food_name AS food, calories AS amount_of_calories, servings as serving_size FROM cal_list where calories > ?" ,[min_cal_amount], function(t,r){ for (var i=0; i < r.rows.length; i++){ food = r.rows.item(i).food; amount_of_calories = r.rows.item(i).amount_of_calories; serving_size = r.rows.item(i).serving_size; list.innerHTML +="<li>"+food+" has "+amount_of_calories+" KCAL worth of calories.</li>"; } }, function(t,e) {alert(e.message);}) } );
First, we determine the number of elements in the query result through
r.rows.length and run from 0 to this value. Each item is available at
r.rows.item (i) , where i is the line number. Column names can be obtained in the same way. To get the value of the
food column, use
r.rows.item (i) .food and so on for the other columns.
We use everything at once
It is possible that you will want to use Web Storage, Application Cache and WebSQL together. It is possible, it all depends on the tasks that need to be solved. For example, if you want to store only a few user preferences, it would be overkill to use WebSQL. For such purposes, Web Storage is better suited.
However, if you have a large amount of data, and you need to somehow handle it, it would be more logical to use WebSQL.
Visit the calorie example page, which
uses all three technologies together : the database is stored in Web Storage, so you can search even if you close or reload the page, AppCache and WebSQL are used to provide the ability to work offline.
Note: you can independently obtain information about which databases are used in Opera and manage them by clicking on the link opera: webdatabases . And get information about the domains that store their data in the browser using Web Storage, and manage them by clicking on the link opera: webstorage . |
Wait ... is the WebSQL specification approved?
Not yet final. But you can already use this technology on the list of browsers and devices. What can not be said about IndexedDB, which has no such cross-platform support. It remains only to wait for the approval of the specification, which will happen soon.
It is also important to note that some desktop versions of browsers, such as Firefox and Internet Explorer, will not support WebSQL, they will work with IndexedDB. In this case, the first place where WebSQL can be used is a standalone data store for smartphones: Opera Mobile 11 browsers are supported, as well as WebKit browsers for Android and iOS platforms.
The good news about WebSQL is that it offers a handy tool for creating a standalone database in a browser. It is easy to learn and use and allows you to quickly develop a stand-alone web application that will work immediately in multiple browsers.
Conclusion
Web applications are now able to work completely offline, using technologies such as Application Cache, Web Storage, and WebSQL databases. We need Application Cache to cache files in order to use them offline; Web Storage - for storing small amounts of information, well, WebSQL will be a convenient tool for working with large amounts of data. Developers, depending on their needs, can use various combinations of these technologies to create stand-alone applications.
Technology promising. And, as usual, there will be races ... WebSQL and IndexedDB, the mentions of which
were already
on the habr . Let them make the world better :)
ps All comments on the translation, as usual, are taken in a personal.
pps somewhere I, apparently, smoothly moved from “web storage” to “local storage”. What is better to leave something? ;)