How to Make an HTML5 iPhone App
This is nice. An article on SixRevisions, short version here for my Archive.
If you write a couple meta tags, your html5 app will look like any other iPhone App, but will also work on Android, PalmPre, etc...
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <link rel="apple-touch-icon" href="iphone_icon.png"/> <link rel="apple-touch-startup-image" href="startup.png" /> <link rel="stylesheet" href="styles.css" type="text/css" media="screen, mobile" title="main" charset="utf-8">
- apple-mobile-web-app-capable: This is another tip-off that we want to be an offline app.
- apple-mobile-web-app-status-bar-style: This hides the status bar, and nav bar when the app is offline.
- apple-touch-icon:This is the pointer to the image that want to be the icon.
- apple-touch-startup-image: This is a url pointing to the startup image.
Application Cache
Application caching allows browsers to determine in advance all the files a web page will need for the web page to work.
One tricky part to this whole thing is that the manifest (the list of files that need to be cached offline) has to be passed with a filetype Header set to text/manifest. That is why you need access to a web server that can set HTTP headers.
CACHE MANIFEST
# Version 3
style.css
index.html
init.js
# offline icons
startup.png
iphone_icon.pngOffline Data
Along with the ability to keep files that are needed offline, you can also store user data in an offline database. There are two major APIs for per user and/or per page data. The first is localStorage. localStorage, is an easy to use key-value store with a dead simple API.
localStorage.dataToStore = 5; console.log(localStorage.dataToStore); // 5
Its also possible to use a webdatabase (SQLite):
// Try and get a database object var db; try { if (window.openDatabase) { db = openDatabase("NoteTest", "1.0", "HTML5 Database API example", 200000); if (!db) alert("Failed to open the database on disk. This is probably because the version was / bad or there is not enough space left in this domain's quota"); } else alert("Couldn't open the database. Please try with a WebKit nightly with this feature enabled"); } catch(err) { } // Check and see if you need to initalize the DB db.transaction(function(tx) { tx.executeSql("SELECT COUNT(*) FROM WebkitStickyNotes", [], function(result) { loadNotes(); }, function(tx, error) { tx.executeSql("CREATE TABLE WebKitStickyNotes (id REAL UNIQUE, note TEXT, timestamp / REAL, left TEXT, top TEXT, zindex REAL)", [], function(result) { loadNotes(); }); }); }); // Insert a test Note. var note = { id: "1", text:" This is a test note", timestamp: "112123000", left:10, top:10, zIndex:2 }; db.transaction(function (tx) { tx.executeSql("INSERT INTO WebKitStickyNotes (id, note, timestamp, left, top, zindex) VALUES / (?, ?, ?, ?, ?, ?)", [note.id, note.text, note.timestamp, note.left, note.top, note.zIndex]); }); // Get all the notes out of the database. db.transaction(function(tx) { tx.executeSql("SELECT id, note, timestamp, left, top, zindex / FROM WebKitStickyNotes", [], function(tx, result) { for (var i = 0; i < result.rows.length; ++i) { var row = result.rows.item(i); var note = new Note(); note.id = row['id']; note.text = row['note']; note.timestamp = row['timestamp']; note.left = row['left']; note.top = row['top']; note.zIndex = row['zindex']; if (row['id'] > highestId) highestId = row['id']; if (row['zindex'] > highestZ) highestZ = row['zindex']; } if (!result.rows.length) newNote(); }, function(tx, error) { alert('Failed to retrieve notes from database - ' + error.message); return; }); });