Working off the grid
HTML5 offline
-
HTML5 offline
-
if (!localStorage.getItem("checkins")) {
localStorage.setItem("checkins", JSON.stringify([]));
}
setItem() getItem() removeItem() clear()
window.sessionStorage
Solution:
var userstr = JSON.stringify({
user: 'john',
id: 10
});
localStorage.setItem('user', userstr);
var user = JSON.parse(localStorage.getItem('user'));
http://example.com:80/
\ \ \_ port
\ \_ domain
\_ scheme
document.querySelector('#ta').addEventListener('keyup', function(e) {
localStorage.setItem('value', this.value);
localStorage.setItem('timestamp', (new Date()).getTime());
}, false);
// This is what our customer data looks like.
const customerData = [
{ ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
{ ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
];
var request = db.setVersion("1.0");
request.onerror = function(event) {
// Handle errors.
};
request.onsuccess = function(event) {
// Create an objectStore to hold information about our customers. We're
// going to use "ssn" as our key path because it's guaranteed to be
// unique.
var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
// Create an index to search customers by name. We may have duplicates
// so we can't use a unique index.
objectStore.createIndex("name", "name", { unique: false });
// Create an index to search customers by email. We want to ensure that
// no two customers have the same email, so use a unique index.
objectStore.createIndex("email", "email", { unique: true });
// Store values in the newly created objectStore.
for (i in customerData) {
objectStore.add(customerData[i]);
}
};
Retrieving by key ( indexes ):
// db.createObjectStore("Friend", "id", true);
db.createIndex("FriendNames", "name", false);
var index = db.openIndex('FriendNames');
var id = index.get('Eric');
Querying ( cursors ):
// Restrict to names beginning A-E
var range = new KeyRange.bound('A', 'E');
var cursor = index.openObjectCursor(range);
while (cursor.continue()) {
console.log(cursor.value.name);
}
var idbRequest = window.indexedDB.open('Database Name');
idbRequest.onsuccess = function(event) {
var db = event.srcElement.result;
var transaction = db.transaction([], IDBTransaction.READ_ONLY);
var curRequest = transaction.objectStore('ObjectStore Name').openCursor();
curRequest.onsuccess = ...;
};
<html manifest="example.appcache">... </html>
CACHE MANIFEST # 2010-11-17-v0.0.1 # Explicitly cached entries CACHE: index.html stylesheet.css images/logo.png # static.html will be served if the user is offline FALLBACK: / /static.html # Resources that require the user to be online. NETWORK: *
text/cache-manifest
applicationCache.addEventListener('updateready', function(e){
if (applicationCache.status ==
applicationCache.UPDATEREADY){
if (confirm('Load new content?')) {
...
}
}
});
window.requestFileSystem( TEMPORARY, // persistent vs. temporary storage 1024 * 1024, // size (bytes) of needed space initFs, // success callback opt_errorHandler // opt. error callback, denial of access );
blob: )data: )filesystem: ) Newvar img = document.createElement('img');
// filesystem:http://example.com/temporary/myfile.png
img.src = fileEntry.toURL();
document.body.appendChild(img);
Retrieve a file by its filesystem URL:
window.resolveLocalFileSystemURL(img.src, function(fileEntry) { ... });
function initFs(fs) {
fs.root.getFile('logFile.txt', {create: true}, function(fileEntry) {
// fileEntry.isFile == true
// fileEntry.name == 'logFile.txt'
// fileEntry.fullPath == '/logFile.txt'
// Get a File obj
fileEntry.file(function(file) { ... }, errorHandler);
// fileEntry.remove(function() {}, errorHandler);
// fileEntry.moveTo(...);
// fileEntry.copyTo(...);
// fileEntry.getParent(function(dirEntry) {}, errorHandler);
}, errorHandler);
}
document.querySelector('#terminal').ondrop = function(e) {
var files = e.dataTransfer.files;
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
Array.prototype.slice.call(files || [], 0).forEach(function(file, i) {
fs.root.getFile(file.name, {create: true, exclusive: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(f); // Note: write() can take a File | Blob.
}, errorHandler);
}, errorHandler);
});
}, errorHandler);
};

navigator.onLine - know when you're all aloneif (navigator.onLine) {
console.log('ONLINE!');
} else {
console.log('Connection flaky');
}
window.addEventListener('online', function(e) {
// Re-sync data with server.
}, false);
window.addEventListener('offline', function(e) {
// Queue up events for server.
}, false);
| Default (Temporary) | Quota Requested (Persistent) | |
|---|---|---|
| Web Storage | 5Mb | N/A |
| App Cache | 10% of available disk in total | |
| IndexedDB | ||
| WebSQL | ||
| File System API | Arbitrary |
// Request Status
webkitStorageInfo.queryUsageAndQuota(webkitStorageInfo.TEMPORARY,
function(used, remaining) {
console.log("Used quota: " + used +
", remaining quota: " + remaining);
}
);
// Request Quota (only for File System API)
webkitStorageInfo.requestQuota(webkitStorageInfo.PERSISTENT,
10 * 1024 * 1024,
function(used) {
console.log("Used quota: " + used +
", remaining quota: " + remaining);
}
);
| Default (Temporary) | Quota Requested (Persistent) | |
|---|---|---|
| Web Storage | 5Mb | N/A |
| App Cache | 10% of available disk in total Used: , bytesremaining: Bytes | |
| IndexedDB | ||
| WebSQL | ||
| File System API | Arbitrary in Bytes Used: Bytes |
![]() |
![]() |
![]() |
| ![]() |
|
|---|---|---|---|---|---|
| Web Storage | Y | Y | Y | Y | Y (8+) |
| IndexedDB | Y | N | Y | N | N |
| WebSQL | N | Y | Y | Y | N |
| App Cache | Y | Y | Y | Y | N |
| File System API | N | N | Y | N | N |
![]() |
![]() |
![]() |
| ![]() |
|
|---|---|---|---|---|---|
| Web Storage | Y | Y | Y (2+) | Y | Y |
| IndexedDB | Y | N | N | N | N |
| WebSQL | N | Y | Y (2+) | Y | N |
| App Cache | Y | Y | Y (2.1+) | Y | N |
| File System API | N | N | Y (3+) | N | N |
For most apps, you can get them packaged up for distribution in a matter of a minute or two. Just go to appmator.com!
Because we're using the application cache, you may want to request the "unlimitedStorage" permission. Just paste it in manually to the manifest.json file.
{
"name": "Great App Name",
"description": "Pithy description",
"version": "0.0.0.1",
"icons": {
"128": "icon_128.png"
},
permissions : [ "unlimitedStorage" ],
"offline_enabled": true,
"app": {
...
}
}
Web Storage (LocalStorage and SessionStorage)
Questions?