html5 api Basic

Let's dive into the wonderland


- Oscar Tong / @oscartong

overview


Evolution of the Web

storage


  • WebStorage
  • WebSQL
  • IndexedDB

WebStorage


  • LocalStorage & SessionStorage
  • Survive browser restart
  • Avoids HTTP overhead of cookie

webstorage - api


  • setItem(key, value)
  • getItem(key)
  • removeItem(key)
  • clear()
  • length

webstorage - example

//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

Demo

webstorage - scope


http://example.com:80/
scheme + host + port

browser support


websql


  • Real relational database (SQLite)
  • Supports transaction

websql - api


  • openDatabase
  • transaction
  • executeSql

websql - example

//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'

browser support


deprecated


W3C no longer actively working on

WebSQL Database Specification

since 2010-11-18


indexed db


  • Allows fast indexing and searching of objects
  • NoSQL, work with JavaScript objects
  • Transaction

indexed db - opening the db


//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
}

indexed db - adding object


//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

indexed db - finding things

Retrieve by key (indexes)
//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);
}


browser support



storage - recap


  • How to store data to WebStorage
  • How to manipulate WebSQL database
  • How to use IndexedDB

offline


  • Application Cache
  • Online/Offline Events

application cache

(AppCache)


  • Allows webapp work without network
  • Reduce server load
  • Speed!

appcache - how it works

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

appcache - manifest

MIME: text/cache-manifest

A simple example:
CACHE MANIFEST
index.html
js/main.js
css/main.css
res/logo.png

appcache - manifest

A more complex example
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

appcache - update

Trigger the update process from JavaScript
//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();
    }
}

browser support



online/offline events


  • Check online status
  • Notify when online status changed

ONLINE/offline events - api


  • navigator.onLine

oneline/offline events - example


//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!! :(');
});

Demo

offline - recap


  • How to use ApplicationCache
  • How to detect online status

file access


  • Basic File Access
  • FileSystem API

Basic file access


  • Access local file (input or d&d)
  • Read file's attributes and content

basic file access - api


  • File
  • FileList
  • FileReader
  • Blob

basic file access - Example

- Select file with form input

Demo

basic file access - example

- Select file with Drag and Drop

Demo

basic file access - example

- Reading file content (Demo)
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);
}

browser support



filesystem api


  • Access sandboxed section of local file system
  • Manipulate files and directories
  • Create, read, write, copy, rename, move, ...

filesystem api - requesting

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
);

filesystem api - quota

//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);
    }
);

filesystem api - file & directory


  • create
  • read
  • write
  • remove

filesystem api - file

- FileEntry
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]);

filesystem api - file

- Creating a file
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);

filesystem api - file

- Reading a file with FileReader
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);

filesystem api - file

- Writing to a file with FileWriter and Blob
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);

filesystem api - file

- Appending data to a file
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);

filesystem api - file

- Removing a file
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);

filesystem api - directory

- DirectoryEntry
directoryEntry.isDirectory === true

directoryEntry.getFile(path[, flags, successCallback, errorCallback]);
directoryEntry.getDirectory(path[, flags, successCallback, errorCallback]);
directoryEntry.removeRecursively(successCallback[, errorCallback]);
directoryEntry.createReader();
...

filesystem api - directory

- Creating a directory
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs){
    fs.root.getDirectory('Pictures', {create:true}, function(directoryEntry){
        //do something with the directory entry
        ...
    }, onError);
}, onError);

filesystem api - directory

- Reading directory's content
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);

filesystem api - directory

- Removing a directory
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);

filesystem api - common operations


  • copy
  • move / rename

filesystem api - copy

- Copying an entry
//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);

filesystem api - move/rename

- Moving or renaming an entry
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);

filesystem api - urls

filesystem: scheme for filling src or href attributes

fileEntry > filesystem:
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
});

filesystem api - demo


HTML5 Terminal

browser support



file access - recap


  • How to read file with form input and D&D
  • How to use local file system api

Web workers


  • JavaScript concurrency
  • performance & security

Webworker - basic


var worker = new Worker('task.js');
worker.postMessage();


  • download asynchronously
  • fail silently if 404

webworker - postmessage

main script
//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);
});

webworker - inline worker

- Create your worker on the fly
//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();

webworker - environment

  • self === this
  • importScripts( ... );
  • ------------------------------------
  • NO DOM (not thread-safe)
  • NO window
  • NO document
  • NO parent

webworker - demo



webworker - demo



browser support



web worker - recap


  • How to start a WebWorker
  • How to communicate with WebWorker
  • Environment of the WebWorker

communication


  • XMLHttpRequest
  • WebSocket
  • WebRTC

XMLHttprequest

(XHR)


  • XHR basic
  • XHR level2 features

xhr basic

  • Asynchronous send HTTP/HTTPS request
  • Loads server response data back to script
//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();

xhr level2 features


  • handle timeout
  • monitor progress
  • cross origin

browser support



websocket


  • bid-direction, full-duplex
  • real-time communication
  • base on HTTP protocol

websocket - demo

WebSocket Chat Room


http://rumpetroll.com/

websocket - how it works


websocket - client side

//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();

browser support



webrtc


  • real-time, p2p communication
  • video, audio, data channel
  • plugin free

webrtx - awesome demos


Webrtc - how it works


communication - recap


  • What is & how to use XHR
  • What's new in XHR Level 2
  • How WebSocket works
  • How WebRTC works

mobile


  • DeviceOrientation
  • DeviceMotion
  • Geolocation

mobile - history



Before & After iPhone

Orientation/MOTION


  • Accelerometer
  • Gyroscope
  • Compass

orientation/motion - xyz

 

orientation/MOTION - api


  • DeviceOrientationEvent
  • alpha (z)
  • beta (x)
  • gamma (y)
  • DeviceMotionEvent
  • acceleration (x,y,z)
  • accelerationIncludingGravity (x,y,z)
  • rotationRate

orientation/motion - example

//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
});
Demo

browser support



geolocation


geolocation - api

- navigator.geolocation

  • getCurrentPosition
  • watchPosition
  • clearWatch

geolocation - example

- Get current location
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
    }
);

geolocation - example

- Monitor user's location
//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);

geolocation - demo


Demo

browser support



mobile - recap


  • Why mobile is special?
  • How to detect orientation & motion
  • How to detect geolocation

thanks


Q&A


Made with Slides.com