ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel

Tutorial on How-To Develop a Google Chrome App | HTML5

Updated on March 7, 2012

HTML5 offers a lot of interesting APIs for programming web applications that reside offline. Interestingly so does Google Chrome through Chromium's own API. In this article I will demonstrate how to create an offline app in Google Chrome using the Offline APIs in HTML5. This is different than the Chrome APIs for creating Installable apps, which can either be a full blown app or a Google Extension.

To take an application offline, a couple of considerations are necessary. First you need to define which assets of your application must be available offline to allow your application to run normally. Second, you need to be able to store data from your app when you are offline but also be able to upload that data to your server, if need be, when the app is back online or least when a synchronization is needed with a server. Finally, you need to be able to update your app from the server with any new features or updates.

To demonstrate these capabilities, I will build a simple address book to store my data locally and to sync with a server.

For this project I am using the Aptana version of Eclipse, which includes templates for HTML5. This is a free download from the Aptana web site. Although, it is possible use the HTML5 Boilerplate templates from Paul Irish, I believe it would be easier to grasp the concepts better by builder the HTML5 app from scratch.

From Eclipse, create a web application project using the appropriate web template (this is a standard template). Click Next and choose the “Basic HTML template”. Click finish to setup the project, which will include the initial index.html file.

Offline Manifest

To add Offline capabilities, you need to define a manifest file to define what assets to download to enable the app to function as if it was on a server. To define a manifest, we will to change the DOCTYPE in the HTML header. In the template, the DOCTYPE is define as:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<!--You will need to change this to :-->

<!DOCTYPE HTML>
<html manifest="addressbook.manifest">

Next you will need to create a manifest file. This can be anything you like but best practices dictate that it should have the manifest extension and be located at the root of your web app folders. You can also store your manifest file online on your web server. This can be a relative path or an absolute path. For an absolute app, it has to be from the same origin as your app. The syntax would be something like:

http://yourserver.com/myapp.manifest

Configure MIME Type

Also the manifest file has to have the correct MIME type, which is: text/cache-manifest.
To handle this, you save the manifest file with the manifest extension and you add the following directive to the .htaccess file on your Apache based server:

AddType text/cache-manifest .manifest

For IIS 6 or 7, you need to define type from the inetMgr tool:

  • Define the MIME type to either be valid for the entire server or to be valid for you application directorie.
  • To add a MIME type to a directory: Right click on the directory in which you want to add the MIME type.
  • Select the HTTP headers tag.
  • Click the File types button at the lower right.
  • Click New type and supply the extension and the content type as listed above.
  • To add a mime type to an entire server; Right click on the server.
  • Click the File types button and follow the instructions above.
  • Click New type and supply the extension and the content type as listed above.



If your app originates on the Google AppEngine, you define your manifest as follows:

- url:/appdir/(.*\.manifest)
static_files: appdir/\1
mime_type: text/cache-manifest
upload: appdir/(.*\.manifest)

For this example, I am naming the file addressbook.manifest and in it I will define the assets (files) that will need to be stored locally. This is the contents of the file:

MANIFEST File Contents

CACHE MANIFEST
# you can add comments using this syntax.
# if your app will only be offline, like if you are building an app for an Android device or an IOS    # device instead of an native app, then you donât necessarily need to include the CACHE
# MANIFEST header. However if the app is web based with offline capabilities, like Google 
# GMail, then you need to include the header information

CACHE:
index.html
styling.css
logic.js

# list any other pages as required. Their paths are relative to the manifest file.
# Any files listed after the CACHE header will load from the AppCache and not
# from the server. Any new files or changes to the server side manifest file will
# trigger the download and update from the server.
 

NETWORK:

# List any files that arenât cached, like any cgi script or types of configuration files or other
# script.

FALLBACK:
# Use this section to identify any files the app should use as failover plan. Any pages or images
# file can be listed here and are loaded if any of the main pages or other files fail to load.

# This is an example and not part of the app
main_logo.png failover_logo.png

It is important to note that 5 mb of data can be stored offline, so it is important to keep these constraints in mind when designing an app.

Updating the Cache



As I mentioned, if the manifest file is altered, then the app will download the new files listed in the manifest, but it won’t necessarily update the other files. As part of the HTML5 offline specification, the API provides programmatic control of the caching. This includes events and status to manipulate the cache of an application.

To add programmatic logic to our app for the caching, define a JavaScript file, logic.js for our app. In the file create a function appInit() which will be called when the app is loaded:

Index.html

<!DOCTYPE HTML>
<html manifest="addressbook.manifest">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Simple Address Book</title>
        <script src='logic.js' language="javascript" type='text/javscript'/>
    </head>
    <body onload='appInit()'>
        <h1>Simple Offline Address Book App</h1>
    </body>
</html>

logic.js

Code from logic.js

/**
 * Cache Update
 */

function appInit(){
	var appCache = window.applicationCache;
	var db = null;
	//Request an cache update
	appCache.update();

	switch (appCache.status) {
	  case appCache.UNCACHED: // 0
	    return 'UNCACHED';
	    break;
	  case appCache.IDLE: // 1
	    return 'IDLE';
	    break;
	  case appCache.CHECKING: // 2
	    return 'CHECKING';
	    break;
	  case appCache.DOWNLOADING: // 3
	    return 'DOWNLOADING';
	    break;
	  case appCache.UPDATEREADY:  // 4
	    return 'UPDATEREADY';
	    break;
	  case appCache.OBSOLETE: // 5
	    return 'OBSOLETE';
	    break;
	  default:
	    return 'UKNOWN CACHE STATUS';
	    break;
	};
	
	//If the update was successful, swap the cache for the new one. 
	if (appCache.status == window.applicationCache.UPDATEREADY) {
		  appCache.swapCache(); 
		  if (confirm('A new version of the Address Book is available. Load it?')) {
		        window.location.reload();
		        launchDb();
		      }
		    } else {
		      // Manifest didn't changed.
		    }
		}
	
}

First we define an appCache variable and set it to window.applicationCache. Next we attempt to update the cache by calling the update method. Then we define the different events that are available. If the update was successful and the event status is UPDATEREADY meaning the dowload of the new files was successful, then we can call the swapCache method to actually update the cache.

Offline Storage


Now that we have our offline app ready for, well, for being offline, we are going to need a place to store our data for our Address Book.

For our example, I will use the Web SQL database. To use, first we will need to create a database if it does not exist and open it. Then create a table, again if it does not exist and finally provide CRUD operations.

var db = null;
function launchDb(){
	db = openDatabase('addrbook', '1.0', 'offline address book database', 5 * 1024 * 1024, createInitTable(db){
	db.transaction(function(tx)
{
	tx.executeSql('CREATE TABLE IF NOT EXIST addresses (id, name, email)');

}
);

});

}

//I will add this code to the appInit function from above and should look like this:


function appInit(){
var db = null;
â¦

	//If the update was successful, swap the cache for the new one. 
	if (appCache.status == window.applicationCache.UPDATEREADY) {
		  appCache.swapCache(); 
		 // init or open the database 
  launchDb();
		}
}

There are most definitely better ways to code this, but for the purposes of our example, it will suffice. Once the cache update is complete, the database and table will attempt to be created and/or opened as well as the table.

We will also need some code next for our CRUD operations; primarily an INSERT and a SELECT query.

function getEntries(db){

db.transaction(
       function(tx) {
           tx.executeSql(
               'SELECT * FROM addresses WHERE date = ? ORDER BY name;',
                  function (tx, result) {
                   for (var i=0; i < result.rows.length; i++) {
                       var row = result.rows.item(i);
           var list = document.getElementById(âdataAddressâ)
                      	list += âname : â + row.name + â,  email:â row.email;
                        }
               },
               errorHandler
           );
       }
   );
}

function insertEntries(db, nameStr, emailStr){
db.transaction(
       function(tx) {
           tx.executeSql('INSERT INTO LOGS 
                        (name, email) VALUES (?, ?'), [nameStr, emailStr];
                        }
               },
               errorHandler
           );
       }
   );

}

Now that we have our back-end and CRUD operations in place, all that is left is to build the UI. For this part, I will use an improved HTML5 features, namely: Form 2.0 and new features that is part of the Web Form API: placeholder text and autofocus

The placeholder attribute adds a prompt or tooltip to the field, while the autofocus places the cursor in a designated field.

So back to our index.html page, insert after the h1 element a form element with two fields: name and email.

<form action=POST>
	<input name=ânameâ placeholder=âEnter a contact nameâ autofocus/>
	<input name=âemailâ placeholder=âEnter a valid e-mail addressâ/>

</form>

So there you have it. This article only brushes on the features of HTML5 for storage and offline capabilities as well as some of the new form features.

Comments

    0 of 8192 characters used
    Post Comment

    • klanguedoc profile imageAUTHOR

      Kevin Languedoc 

      5 years ago from Canada

      Usually an extension remains open as long as the Chrome browser is open. Do you mean to want it the stay on top. Have you tried z-index. The answer is not really in Chrome, but in CSS

    • profile image

      Eddwin Paz 

      5 years ago

      Hi, you have any idea how i can prevent closing a Extension? example i want to make a Small Phone Agenda but when i to no another page or click somewhere else it closes and when i click back the form its blank again.

      Any ideas? i wanted to try a tab extension but don't know where to go.

      Thanks!

    • klanguedoc profile imageAUTHOR

      Kevin Languedoc 

      6 years ago from Canada

      Hi Edward,

      Thanks for the great feedback. I would certainly like to write more about HTML5 and and how to use to develop web apps.

    • profile image

      Edward 

      6 years ago

      Hey Klanguedoc,

      Looks pretty descriptive for newbies like myself to learn on how to chrome appsusing HTML5.HTML5 also finds its big way in responsive web designing ,it would be of great use for readers if u explain on tat since ur presentation is great..

      I loved reading ur article and wish more related posts from you..

    • klanguedoc profile imageAUTHOR

      Kevin Languedoc 

      6 years ago from Canada

      I am glad you found it useful. Thanks for the feedback

    • profile image

      Jagan 

      6 years ago

      WOW... Such a awesome tutorial !

      Thanks =)

    working

    This website uses cookies

    As a user in the EEA, your approval is needed on a few things. To provide a better website experience, hubpages.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

    For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: https://hubpages.com/privacy-policy#gdpr

    Show Details
    Necessary
    HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
    LoginThis is necessary to sign in to the HubPages Service.
    Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
    AkismetThis is used to detect comment spam. (Privacy Policy)
    HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
    HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
    Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
    CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
    Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
    Features
    Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
    Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
    Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
    Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
    Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
    VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
    PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
    Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
    MavenThis supports the Maven widget and search functionality. (Privacy Policy)
    Marketing
    Google AdSenseThis is an ad network. (Privacy Policy)
    Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
    Index ExchangeThis is an ad network. (Privacy Policy)
    SovrnThis is an ad network. (Privacy Policy)
    Facebook AdsThis is an ad network. (Privacy Policy)
    Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
    AppNexusThis is an ad network. (Privacy Policy)
    OpenxThis is an ad network. (Privacy Policy)
    Rubicon ProjectThis is an ad network. (Privacy Policy)
    TripleLiftThis is an ad network. (Privacy Policy)
    Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
    Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
    Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
    Statistics
    Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
    ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
    Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)