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