HTML5 Client Facilities

Browser Storage

Contrasts with Cookies

Local Storage and Session Storage

IndexedDB

Background Workers

Dedicated vs Shared

APIs available / not available

Demo: Syntax highlighting

// host page
// hostWorker: link to the bg thread
const scriptToExecute = 'worker.js'
const hostWorker = new Worker(scriptToExecute)
hostWorker.onmessage = ({data}) => {
  if (data.markup) {
    // inject into the DOM the markup returned from bg thread
    demo.$result.innerHTML = data.markup;
  }
}

// initiate bg job by posting message
hostWorker.postMessage({ command: 'start.syntaxHighlighting' })


// import highlight.js
importScripts('/scripts/highlightjs/highlight.pack.js')
// highlight.js run in `self` scope

const worker = {
  message: async e => {
    try {
      const response = await fetch('message.js')
      const data = await response.text()
      const code = ['// from worker', data].join("\n")
      // `self` is a ref to the worker's global context
      const result = self.hljs.highlightAuto(code)
      postMessage({ message: 'done', markup: result.value })
    } catch (ex) {
      postMessage({ type: 'error', message: ex })
    }
  }
}

// listen for events and handle when emitted
addEventListener('message', worker.message)

Progressive Web Apps

Service worker

Cache API

const cache = await window.caches.open(CACHE_NAME)
cache.put(url, resp.clone())

const keys = await cache.keys()
keys.forEach(request => console.log(request.url))

const match = await cache.match(url)
await cache.delete(url)

WebSockets

Demo

Dependencies: http-server, ws

// client
const ws = new WebSocket("ws://127.0.0.1:8181")
ws.onopen = event => {
  ws.send(`[${event.timeStamp}] Hello from the client!`)
}
ws.onmessage = message => {
  console.log(`Client: ${message.data}`)
}

// server
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 8181 })

wss.on('connection', ws => {
  ws.on('message', message => {
    console.log(`Received: ${message}`)
    ws.send(`Server: ${message}`)
  })

  setTimeout(() => {
    ws.send('Hi again! (after 3 seconds)')
  }, 3000)
})

Geolocation

Location detection

Demo: Get current position

navigator.geolocation.getCurrentPosition({
  position => {
    console.log(position)
    console.log(position.coords.latitude)
    console.log(position.coords.longitude)
    console.log(position.coords.accuracy)
  },
  error => {
    console.log(error)

    switch(error.code) {
    case 0:
      console.log('Unknown error')
      break
    case 1:
      console.log('Permission denied')
      break
    case 2:
      console.log('Position unavailable')
      break
    case 3:
      console.log('Timeout reached')
      break
    }
  }
})

Demo: Watch position

let watchID = null

function watchPosition() => {
  watchID = navigator.geolocation.watchPosition(
    position => {
      console.log(position)
    },
    error => {
      console.log(error)
    },
    {
      enableHighAccuracy: true, // default false
      timeout: 10000,   // 10s, default noone
      maximumAge: 2000, // 2s, default 0
    }
  )
}

function stop() => {
  navigator.geolocation.clearWatch(watchID)
}