Oscar Tong
Everything that has a beginning has an end.
Let's dive into the wonderland
- Oscar Tong / @oscartong
//save data to localStorage
localStorage.foo = 'bar';
localStorage.setItem('foo', 'bar');
//get data from localStorage
localStorage.foo;
> 'bar'
localStorage.getItem('foo');
> 'bar'
localStorage.length;
> 1
//remove data from localStorage
delete localStorage['foo'];
localStorage.removeItem('foo');
localStorage.clear();
localStorage.foo;
> undefined
//create & open the database
var db = openDatabase('myDb', '1.0', 'hello world database', 2*1024*1024);
//create table within the database and populate it
db.transaction(function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS foo (id unique, name)');
tx.executeSql('INSERT INTO foo (id, name) VALUES (1, "Lucy")');
tx.executeSql('INSERT INTO foo (id, name) VALUES (?, ?)', [2, 'Jack']);
//query items
tx.executeSql('SELECT * FROM foo', [], function(tx, results){
var i, length = results.rows.length;
for(i=0; i<length; i++){
console.log(results.rows.item(i).name);
}
});
});
> 'Lucy'
> 'Jack'
W3C no longer actively working on
WebSQL Database Specification
since 2010-11-18

//opening the database
var db = indexedDB.open('mydb');
//check version and do initialization
if(db.version !== '1'){
db.createObjectStore(
'todoList', //new object store's name
'id', //key path
true //auto increment?
);
db.setVersion('1');
}
else{
//database already initialized
}
//open object store
var store = db.openObjectStore('todoList');
//adding object to the store
var user = store.put({
name: 'Oscar',
gender: 'male',
age: 26,
love: 'html5'
});
//expect id=1
console.log(user.id);
> 1
//db.createIndex(indexName, keyPath, unique);
db.createIndex('FriendNames', 'name', false);
var index = db.openIndex('FriendNames');
var id = index.get('Oscar');
Query
//restrict to names from H to Q
var range = new KeyRange.bound('H', 'Q');
var cursor = index.openObjectCursor(range);
while(cursor.continue()){
console.log(cursor.value.name);
}

<html manifest="test.appcache"> ... </html> <html manifest="http://www.test.com/appcache.mf"> ... </html>

CACHE MANIFEST index.html js/main.js css/main.css res/logo.png
CACHE MANIFEST #2012-11-19 v1 #Explicity cached 'master entries' CACHE: index.html ... #Resources that require the user to be online NETWORK: login.php /someAPI http://api.twitter.com #replacements when resources are inaccessible FALLBACK: /main.py /static.html images/large/ image/offline.jpg *.html /offline.html
//try to update the user's cache
var appcache = window.applicationCache;
appcache.update();
...
//if the fetch is successful, swap in the new cache
if(appcache.status === window.applicationCache.UPDATEREADY){
appcache.swapCache();
//ask user to reload the page
if(confirm('A new version is available, reload now?')){
window.location.reload();
}
}

//check online status
navigator.onLine;
> true
//listen for online/offline events
window.addEventListener('online', function(){
console.log('You are online :)');
});
window.addEventListener('offline', function(){
console.warn('You are offline!! :(');
});
var files = event.target.files;
for(var i=0, f; f=files[i]; i++){
//ony process image files
if(!f.type.match('image.*')) continue;
//create the file reader
var reader = new FileReader();
reader.onload = (function(theFile){
return function(e){
//file content is in e.target.result
console.log(e.target.result);
var img = document.createElement('img');
img.src = e.target.result;
...
};
})(f);
//start reading the file
reader.readAsDataURL(f);
}

window.requestFileSystem(type, size, successCallback[, errorCallback]);type = window.TEMPORARY / PERSISTENT
function onInitFs(fs){
console.log('File system opened: ' + fs.name);
}
window.requestFileSystem(
window.TEMPORARY,
5*1024*1024,
onInitFs,
onInitError
);
//request persistent storage
window.webkitStorageInfo.requestQuota(
PERSISTENT,
1024*1024,
//request approved :)
//now we can request persistent filesystem with the granted storage
function(grantedBytes){
window.requestFileSystem(
PERSISTENT,
grantedBytes,
onInitFs,
onInitError
);
},
//request denied :(
function(e){
console.error('QUOTA REQUEST FAIL', e);
}
);
fileEntry.isFile === true fileEntry.isDirectory === false fileEntry.name fileEntry.fullPath ... //get the file object (for reading content) fileEntry.file(successCallback[, errorCallback]); //create a new FileWriter fileEntry.createWriter(successCallback[, errorCallback]); ... fileEntry.getMetadata(successCallback[, errorCallback]); fileEntry.getParent(successCallback[, errorCallback]); fileEntry.copyTo(directoryEntry[, newName, successCallback, errorCallback]); fileEntry.moveTo(directoryEntry[, newName, successCallback, errorCallback]); fileEntry.remove(successCallback[, errorCallback]); fileEntry.toURL([mimeType]);
function onInitFs(fs){
fs.root.getFile('foo.txt', {create:true, exclusive:true}, function(fileEntry){
//fileEntry.isFile === true
//fileEntry.name == 'foo.txt'
//fileEntry.fullPath == '/foo.txt'
}, onError);
}
window.requestFileSystem(window.TEMPORARY,1024*1024,onInitFs,onError);
function onInitFs(fs){
fs.root.getFile('foo.txt', {}, function(fileEntry)
{
//get the file object, then user FileReader to read its content
fileEntry.file(function(file){
var reader = new FileReader();
reader.onloadend = function(e){
console.log(reader.result);
//should be an empty string since we just newly created the file
};
}, onError);
}, onError);
}
window.requestFileSystem(window.TEMPORARY,1024*1024,onInitFs,onError);
function onInitFs(fs){
fs.root.getFile('foo.txt', {create:true}, function(fileEntry)
{
//create a FileWriter object for our FileEntry
fileEntry.createWriter(function(fileWriter){
//listen for writeend and error event of the FileWriter
fileWriter.onwriteend = function(e){ /* Write completed */ };
fileWriter.onerror = function(e){ /* Write fail */ };
//create a new Blob and write it to foo.txt
//after writeend event, the file's content should be: "Hello World"
var blob = new Blob(['Hello World'], {type:'text/plain'});
fileWriter.write(blob);
}, onError);
}, onError);
}
window.requestFileSystem(window.TEMPORARY,1024*1024,onInitFs,onError);
function onInitFs(fs){
fs.root.getFile('foo.txt', {create:false}, function(fileEntry)
{
//create a FileWriter object for our FileEntry
fileEntry.createWriter(function(fileWriter)
{
//start with position at EOF
fileWriter.seek(fileWriter.length);
//create a new Blob and write it to foo.txt
//if write success, content should be: "Hello World, FileSystem"
var blob = new Blob([', FileSystem'], {type:'text/plain'});
fileWriter.write(blob);
}, onError);
}, onError);
}
window.requestFileSystem(window.TEMPORARY,1024*1024,onInitFs,onError);
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs){
fs.root.getFile('foo.txt', {create:false}, function(fileEntry)
{
//remove the file entry
fileEntry.remove(function(){
console.log('File is removed');
}, onError);
}, onError);
}, onError);
directoryEntry.isDirectory === true directoryEntry.getFile(path[, flags, successCallback, errorCallback]); directoryEntry.getDirectory(path[, flags, successCallback, errorCallback]); directoryEntry.removeRecursively(successCallback[, errorCallback]); directoryEntry.createReader(); ...
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs){
fs.root.getDirectory('Pictures', {create:true}, function(directoryEntry){
//do something with the directory entry
...
}, onError);
}, onError);
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs)
{
//create a new DirectoryReader to read entries from root directory
var directoryReader = fs.root.createReader();
//read entries until no more results are returned
var readEntries = function(){
directoryReader.readEntries(function(results){
if(!result.length){
console.log('all entries are listed');
}
else{
console.log('entries: ', results);
readEntries();
}
}, onError);
};
readEntries();
}, onError);
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs){
fs.root.getDirectory('myPictures', {}, function(directoryEntry)
{
//remove the directory
//if the directory is not empty, an error will be thrown
directoryEntry.remove(function(){
console.log('Directory is removed');
}, onError);
//or you can:
//remove the directory and all its content (subdirectories, files) recursively
directoryEntry.removeRecursively(function(){
console.log('The directory and all its sub-entries are removed');
}, onError);
}, onError);
}, onError);
//copy /folder1/foo.png to /folder2/bar/
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs){
fs.root.getFile('/folder1/foo.png', {}, function(fileEntry){
fs.root.getDirectory('/folder2/bar/', {}, function(directoryEntry)
{
//use copyTo method to copy a file entry
fileEntry.copyTo(directoryEntry);
}, onError);
}, onError);
}, onError);
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs){
fs.root.getFile('foo.png', {}, function(fileEntry)
{
//moving an entry to a different directory
fileEntry.moveTo('someNewFolder/');
//or renaming an entry by moving the entry to the same
//directory with a different name
fileEntry.moveTo(fs.root, 'bar.png');
}, onError);
}, onError);
var img = document.createElement('img');
img.src = fileEntry.toURL(); //filesystem:http://example.com/temporary/foo.png
document.body.appendChild(img);
filesystem: > fileEntry
var url = 'filesystem:http://example.com/temporary/foo.png';
window.resolveLocalFileSystemURL(url, function(fileEntry){
//do something with the file entry
});


var worker = new Worker('task.js');
worker.postMessage();
//create a worker and listen for its message
var worker = new Worker('doSomething.js');
worker.addEventListener('message', function(e){
console.log('worker said: ', e.data);
}, false);
//tell worker to start
worker.postMessage('get to work!');
doSomething.js
self.addEventListener('message', function(e){
//working hard ...
//this may take some time ...
//hold on ...
//done!
self.postMessage(e.data);
});
//put the worker's code in a blob
var blob = new Blob([
'onmessage = function(e){ postMessage("msg from worker"); }'
]);
//obtain a blob url reference (like a real 'file'), the url looks like this:
//blob:http://localhost/c745ef73-ece9-46da-8f66-ebes5747789b1
var blobURL = window.URL.createObjectURL(blob);
//create and start the worker
var worker = new Worker(blobURL);
worker.onmessage = function(e){
//e.data == 'msg from worker'
};
worker.postMessage();

//create a XHR instance
var request = new XMLHttpRequest();
request.open('GET', 'http://www.example.com/foo', true);
//listen for readyStateChange event
request.onreadystatechange = function(e){
if(request.readyState === 4 && request.status === 200){
console.log(request.responseText);
}
};
//send request
request.send();


//creating a WebSocket instance and try connect to the server
var socket = new WebSocket('ws://www.example.com/socketserver');
//open event is fired when WebSocket is connected
socket.onopen = function(event){
socket.send('Hello Server. How are you?');
};
//message event is fire when message is received from server
socket.onmessage = function(event){
console.log('Server said:', event.data);
};
...
//close the WebSocket connection
socket.close();




//deviceorientation event represents the orientation of the device
window.addEventListener('deviceorientation', function(event){
console.log(event.alpha, event.beta, event.gamma);
});
//devicemotion event represents the "change" of the
//device's orientation and acceleration
window.addEventListener('devicemotion', function(event){
console.log(event.rotationRate); //alpha, beta, gamma
console.log(event.acceleration); //x, y, z
console.log(event.accelerationIncludingGravity); //x, y, z
});


navigator.geolocation.getCurrentPosition(
function(position){
console.log(position.coords.latitude);
console.log(position.coords.longitude);
},
function(error){
console.error('ERROR OCCURRED', error.code);
//possible error code:
//0: unknown error
//1: permission denied
//2: position unavailable
//3: timed out
}
);
//keep watching user's location
var watchID = navigator.geolocation.watchPosition(
function(position){
console.log(position.coords.latitude);
console.log(position.coords.longitude);
},
//optional error handler
onError,
//optional position configurations
{enableHighAccuracy:true, maximumAge:30000, timeout:10000}
);
...
navigator.gelocation.clearWatch(watchID);


By Oscar Tong