Web APIs

... my browser can do what?!

v1.2.0

Who controls what?

Pretty much everything you do via JavaScript in the browser - if it isn't a native JS instruction - is part of a Web API.

Who controls or directs the Web API:

  • World Wide Web Consortium (W3C)
  • Web Hypertext Application Technology Working Group (WHATWG)
  • ...and in coordination with IETF, TC39, and others

No really, who controls what?

It's confusing between W3C and WHATWG do, but basically this is how it has been:

  • W3C controls "standard" HTMLx.x (5.2 "recommendation" in 2017, 5.3 is "Public Working Draft" in 2018)
  • WHATWG maintains a "Living Standard" which is never complete, but tracks what "is" and is somewhat aspirational

A New Hope

But in May of 2019:

W3C and the WHATWG signed an agreement to collaborate on a single version of HTML and DOM

Woot!

JavaScript

  • JavaScript the language is officially known as "ECMAscript"
  • It's controlled by the ECMA TC39 task group
  • There's a 5 stage process from "Proposal" to "Finished" that changes go through
  • Then of course you have to wait for the Browsers to implement, if they haven't already started - or if they've implemented a incompatible/incomplete version

Interfaces vs APIs vs Objects

  • Generally, an "API" is a set of technologies exposed as Interfaces and JS Objects
  • Interfaces are a set of properties and methods
  • Objects are an instance of an Interface

Plus there's substantial overlap and/or dependencies between many of APIs and Interfaces.

Window vs Document vs Navigator

From MDN:

  • The window object represents a "window" and implements the Window interface
  • The DOM document is located at window.document
  • The Navigator interface represents the state and the identity of the user agent
  • A Navigator object is located at window.navigator

Things within the window object can generally be accessed without stating "window"


window
// $: ƒ (selector,context) //  jQuery is loaded
// document: document // document is an instance of document
// fetch: ƒ fetch()
// location: Location {replace: ƒ, assign: ƒ, href: "https://developer.mozilla..." /* ... */ }
// navigator: Navigator {productSub: "20030107", vendor: "Google Inc." /* ... */ }
// etc.

window.document
document // these are equivalent
// #document
//	
//	
// etc.

window.navigator
navigator // these are equivalent
// appCodeName: "Mozilla" //  using Chrome for these next three
// appName: "Netscape"
// product: "Gecko"
// language: "en-US"
// platform: "MacIntel"
// userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 1..."
// serviceWorker: ServiceWorkerContainer ...
// etc.

Compatibility

Not all of these are widely supported or even well supported, some are experimental, and some aren't even on standards tracks - but depending on your use case they may be sufficient.

For Web APIs, polyfills/shims more often fill-in newer features than present an entire missing API.

Some are available in Web Workers or Service Workers.

Compatibility, cont.

Apple's the new IE :/

Chromium's the new Edge (literally)*

I've listed some rough compatibility info, but for complete info keep checking:

  • https://caniuse.com/
  • https://developer.mozilla.org/en-US/docs/Web/API *

* Also Chromium: Opera, Samsung Internet, Brave Browser, and more. ** Did you know since 2017 "MDN Web Docs" hass becoming an industry collaboration?

Canvas API

Draw 2D graphics, including text, composition, transformations, animations, video processing and rendering.

  • Started with HTML5
  • Interactivity can be done using experimental HitRegions
  • <canvas> can also be used by WebGL and others

Compatible since IE9

Popular libs:

  • fabric.js
  • kinetic.js
  • paper.js
  • p5.js
  • ... and many more

<canvas id="canvas"> </canvas>

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

ctx.fillStyle = 'green';
ctx.beginPath();
ctx.moveTo(75, 50);
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill();

Performance Interface

Provides performance data for the page. Leverages High Resolution Time, Performance Timeline, Navigation Timing, User Timing, and the Resource Timing APIs.

There's a bunch of methods and properties, which are variously supported.

Compatibility: Various methods widely compatible since IE9 to only recently compatible in only Chrome.

See also the Frame Timing API


performance.mark('testStart1');
// do something interesting
performance.mark('testEnd1');
performance.getEntries();
// ...
// PerformanceMark {name: "testStart1", entryType: "mark", startTime: 829106.9000000134, duration: 0}
// PerformanceMark {name: "testEnd1", entryType: "mark", startTime: 847141.100000008, duration: 0}

performance.measure('testMeasure', 'testStart1', 'testEnd1');
var testMeasure = performance.getEntriesByName("testMeasure");
console.log(testMeasure[0]);
// duration: 18034.1999999946
// entryType: "measure"
// name: "testMeasure"
// startTime: 829106.9000000134

Security

Some browsers, Firebox 60 at least, have reduced precision of, or possible added slight randomizations to, various timing responses.

Some precision can be removed/restored through Browser flags.

Some argue that reduced precision doesn't matter as loops can provide missing accuracy.

  • Various "side channel" attacks (Meltdown/Spectre) came to public awareness Mar '18
  • "The Spy in the Sandbox – Practical Cache Attacks in Javascript" (Mar '15)
  • In general, many prior similar vulnerabilities back to 2002

// Chrome 65:
performance.now();
// 8379497.000000032
// Chrome 66+:
// TBD...

// Firefox 58:
performance.now();
// 32555.22
// Firefox 59:
performance.now();
// 29120
// FF 59 w/privacy.reduceTimerPrecision false
performance.now();
// 349440.56

Payment Request API

Enables a Merchant site to hand-off the payment request (including payment options criteria) to the browser, which then presents the user with a choice of user-appropriate Payment services.

Basically this means your website doesn't need a payment gateway as you can just use the Browser's API; this means the user only has to trust the Browser/device (like their phone).

  • Requires HTTPS
  • Utilizes device native UIs

There's a lot to this API... look for it to make more of a impact in the (near) future.

Compatibility: Chrome 61, Edge, FireFox 55 (flag), Safari 11.1

Location Interface

This is not geographic location but rather the URL of an object (often an a link). It includes a bunch of properties breaking down the URL, and a few methods to manipulate it.

Location is both an Object and an Interface that an element might have.

Compatibility: most browsers.

Interface


var a = document.getElementsByTagName("a");

console.log(a[0].href);
// https://stackoverflow.com/
console.log(a[0].protocol);
// https:
console.log(a[0].hostname);
// stackoverflow.com
 

Object


window.location
// host: "stackoverflow.com" // could include port
// hostname: "stackoverflow.com"
// href: "https://stackoverflow.com/users/3304856/todd-zebert"
// origin: "https://stackoverflow.com"
// pathname: "/users/3304856/todd-zebert"
// protocol: "https:"
window.location = "https://stackoverflow.com";
// navigates to https://stackoverflow.com
window.location.reload(true);
// true forces reload from server
window.location.replace("https://stackoverflow.com/users");
// navigate saving the last location in History
 

Indexed Database API

aka IndexedDB

A low-level client-side API for storing structured data, which is both indexed and transactional.

As compared to Web Storage, IndexedDB is better for larger amounts of data. *

  • Follows the same-origin policy
  • Asynchronous
  • Uses callbacks and defined event handlers

* Web Storage is usually limited to a few Meg per origin.

IndexedDB

  • Uses Key-Value pairs
    • Keys can any of a few JS data types but they must be used in an ordered sequence
    • Values can be essentially any JS data type plus Blobs* and files
  • Indexes are used for finding records quickly
  • Cursors are used to iterate over keys or an index in a direction, for retrieving records

* Blobs are Binary Large Objects.

Storage

Storage limits depend on the browser, platform, (free?)space.

On desktop, a couple or more GB is probably safe in most cases, and even more is likely OK.

Some browsers ask the user if any individual "large" value is OK to store.

"Eviction" happens when the browser needs to free up space, and it's complicated (although often some variation on LRU) and various across browsers.

Libs, Vers, Compatibility

Frankly, given the complexity of this API, unless you have unique needs, it's much easier to use a library, such as: localForage, dexieJS, ZangoDB and JsStore.

It's gone through a major revision, v2.0 draft as of Jan 2018.

Compatibility: for V1 IE10 (partial), Safari 10 (7.1 partial), Chrome, Firefox; for v2 "Chromium Edge", FireFox, Chrome, Safari 10.1

Web MIDI API

An API allowing bi-directional low-level protocol MIDI access (beyond General MIDI)

Seemed like this was going to die, but it's now "Editor's Draft 22 August 2019"

Compatibility: Right now just Chrome (and Opera, "Chromium Edge")

Try WebMIDIAPIShim otherwise. There's also desktop MIDI device simulators.


if (navigator.requestMIDIAccess) {
  navigator.requestMIDIAccess()
    .then(onMIDISuccess, onMIDIFailure);
}

function onMIDISuccess(midiAccess) {
  var inputs = midiAccess.inputs;
  var outputs = midiAccess.outputs;

  midiAccess.onstatechange = onMIDIStateChange;

  for (var input of inputs.values()) {
    input.onmidimessage = onMIDIMessage;
  }
}

function onMIDIMessage(midiMessage) {
  // do something with midiMessage object
}

function onMIDIStateChange() { /* ... */ }

function onMIDIFailure() { /* ... */ }
  • MIDIAccess interface:
    • See input and output objects in the code sample
    • properties about the port (manufacturer, type, version, etc.)
  • midiMessage object:
    • data property, an array of bytes:
      • The 1st byte is the command
      • For noteOn and noteOff:
        • The 2nd byte is the note, ex: 60 is middle C
        • The 3rd byte is the "velocity" (0-128)

GPU on the Web (WebGPU)

Apple (surprisingly) via WebKit proposed a new W3C Working Group on 3D web graphics and put forth an API proposal.

... API that exposes modern GPU features including low-level graphics and general purpose computation

As compared to WebGL it's much lower level and should offer better performance.

Compatibility: Only very recent Safari behind a flag*. Highly experimental. Chrome (2017) intends to implement.

I couldn't get it to work on my Late 2011 Macbook but my 2017 worked.


let canvas = document.querySelector("canvas");
let gpu = canvas.getContext("webgpu");
// etc

Notifications API

A cross-platform native system (outside the page) user notifications API.

Generally, the user needs to grant permission for these notifications.

Compatibilty: IE none; Edge 14, Chrome, Firefox, Safari.


Notification.requestPermission().then(function(result) {
  if (result === "granted") {
    var notification = new Notification("Yo.", {
      body: 'Yo, Adrian.',
      icon: '../images/notifications/yo-128x128.png',
      vibrate: [300, 100, 300, 100],
      tag: 'yo-notification'
      }
    );
  }
});

"developer.mozilla.org" is shown as that's the page I was testing code on via the JS console.

Screen Interface

Part of window, it provides properties that report on the (usually physical) screen the current (Browser) window is on.

Compatibilty: Well supported.


screen.availTop; // 23 // this excludes (semi) permament UI features
screen.top; // undefined
screen.availLeft; // 0
screen.availWidth; // 1280
screen.availLeft; // 0
screen.availHeight; // 777
screen.colorDepth; // 24
screen.orientation;
// {angle: 0, type: "landscape-primary", onchange: null}
screen.lockOrientation()
// VM364:1 Uncaught TypeError: screen.lockOrientation is not a function
// that method only avail on certain devices in certain circumstances
 

Selection and Range objects

Report on and manipulate the text of the user's selection or cursor position

  • Selections are composed of Ranges
  • Anchor is where the selection began
  • Focus is where the selection ended

Some browsers support only 1 range per selection, others multiple.

Compatibility: Widely supported, although considered experimental, as additions and changes are frequent.


var s = window.getSelection();
// {anchorNode: text, anchorOffset: 89,
//   focusOffset: 74, rangeCount: 1, type: "Range", …}
s.deleteFromDocument();
var r = s.getRangeAt(0); // assuming you didn't delete above
// Range
//   startOffset: 26
//   endOffset: 42
//   endContainer: text /* ... */
//   startContainer: text /* ... */
//   commonAncestorContainer: text
//     data: "Each message received has some combination of the following fields, one per line:"
// my selected text was "some combination"
// startContainer and endContainer exist as ranges may go across multiple elements
 

Service Workers & Web Workers

Since JavaScript is single threaded and subject to its event loop, these "workers" provide ways for background tasks to run, and "threading".

These Workers are responsive yet do not affect the UI's responsiveness.

Neither can directly interact with the DOM, have very resticted access, and are limited to communication through a special method.

Service Worker

SW are a network proxy that allow more control over network requests.

They are essential for building offline-first and/or PWA (Progressive Web Apps) and handling things like periodic background syncs, inconsistent network connectivity, push notifications, smart caching, and the like.

They in essence replace the App Cache API that had a number of flaws.

Service Worker, 2

Service Workers can use localhost but otherwise must use HTTPS.

SW's are too complex to offer any simple examples.

SW's are supported by Chrome, Firefox, Safari 11.1 (iOS Safari 11.3), and Edge 17.

Web Workers

WW are general purpose "threads" in which to run computationally intensive processes outside of the main UI thread.

Given JS's "run-to-completion" event loop, "blocking" code is quite easy to create; so run it in a WW.

They come in two flavors, Dedicated and Shared:

  • Dedicated are only accessible from the parent script
  • Shared are accessible from any script from that same domain

WW Example


// main code
var myWorker = new Worker('my-task.js');
myWorker.addEventListener('aMessage', function(e) {
  console.log('from worker: ', e.data);
}, false);
myWorker.postMessage(messageObj); // Start worker & pass message
						

// in my-task.js
self.addEventListener('aMessage', function(e) {
  self.postMessage(e.data); // this just returns message
}, false);
						

Dedicated WW's are well supported (even IE11), but Shared WW Chrome and FF only.

Communication protocols

  • XHR: classic client to server
  • Fetch: modern replacement for XHR
  • WebSockets: bidirectional client-server
  • Sever-Sent Events: unidirectional server-initiated
  • Push API: like Server-Sent but works "offline"
  • WebRTC API: bidirectional client to client (or server)

XHR (XMLHttpRequest) API

Send unidirectional network requests from the client to the server. One of the core parts of the Ajax programming technique.

Asynchronous (Sync option has been deprecated).

Compatibility: Long standing wide support but some additions and changes are still rolling out.


function onLoad() {
  console.log(this.responseText);
}

var req = new XMLHttpRequest();
req.addEventListener("load", onLoad);
req.open(
  "GET",
  "https://stackoverflow.com/users/3304856/todd-zebert"
);
req.send();
 

Fetch API

A newer, more flexible and powerful way of doing the same functionality XMLHttpRequest provided.

It's what all the cool kids are doing.

Uses Promises; and new implementations include support for Streams.

Compatibility: IE none, Edge 14, Safari 10.1, Chrome, FireFox. There's a window.fetch polyfill.

Get


fetch('https://stackoverflow.com/users/3304856/todd-zebert')
  .then(function(response) {
    return response.text(); // or use .json(), etc as appropriate
  })
  .then(function(data) {
    console.log(data);
  });

Post


fetch('https://mysite/endpoint', {
  body: JSON.stringify(data),
  cache: 'no-cache', // optional
  headers: {
    'content-type': 'application/json' // matches body
  },
  method: 'POST',
  mode: 'cors', // optional
})
  .then(response => response.json()) // parses response to JSON
	

WebSockets API

Open and maintain a communication session between server and client. This avoids repeated session requests/polling, Flash, or "long-polling".

WebSockets make possible the (efficient) dynamic updating of sites/apps we've come to expect, like chat, collaboration, mail, etc.

There's been preliminary versions but now RFC 6455 is standard. Compatible since IE10, Safari 6, etc.

Popular libraries include Socket.IO, ws (Node), web_socket.js (supports Flash fallback), SockJS, etc.

Libraries will generally include things like heatbeats, reconnects and maybe http fallback.

There's no direct polyfill, but a couple shims utilize Flash (or long-polling) to simulate the same result.


const socket = new WebSocket('ws://localhost:8080');

socket.addEventListener('open', function (event) {
  socket.send('some message'); // or whatever data
});

socket.addEventListener('message', function (event) {
  // do something with event.data
});

socket.close(); // at appropriate time

Server-Sent Event API

Allows server initiated communication to the client.

On the client side it uses the EventSource interface to accept messages and events.

Compatibility: IE/Edge none ("Chromium Edge" yes); Chrome/Firefox/Safari yes.

Stream Format

Server-Sent events are unusual as the payload ("stream") the server sends is first parsed by the browser then provided to the JS code:

  • There can be multiple "notifications" per server transmission
  • Each notification is terminated by two newline characters
  • Each line within a notification is a "field" which are separated by a single newline
  • Fields are composed of a name, a colon, and a value
  • Fields starting with a colon are "comments"
  • Fields without a colon are considered an entire field name, with no data

	var evtSource = new EventSource(
	  "my-event-generating-uri",
	  { /* options */ }
	);
	// messages: notifications with no event field
	evtSource.onmessage = function(e) {
	  // do something with e.data
	}
	// events:
	evtSource.addEventListener("my-event", function(e) {
	  // do something with e.data
	}, false);
	 

Data example


: this is a comment

data: a data field with this as value
data: an optional second line of value

event: an-event

event: an-event-with-data
data: some string data

data: there's also "id" and "retry" fields
data: all other field names are ignored

event: json-as-string
data: {"answer": "42", "question": "We don't know yet."}
 

Push API

Enables server to client messaging but differently from Sever-Sent Events (or others) by relying on Service Workers that can receive messages even if the "web app" is not loaded.

Most frequently used with the Notifications API.

The code is too complex to go into here.

Compatibility: IE none, Edge 17, Chrome and Firefox yes, Safari no*.

pushjs.org offers something of a cross-browser replacement.

* Safari has it's own Apple-centric system window.safari.pushNotification. Service Workers now supported since Safari 11.1

WebRTC API

Web Real-Time Communications

Allows direct client to client (or client server) streaming communications, generally used for audio and/or video.

Utilizes the RTCPeerConnection interface for one or more MediaStream and/or RTCDataChannel interfaces.

MediaStreams are comprised of one or more MediaStreamTrack interfaces.

RTCDataChannels are used for non-media data.

Often used with Media Capture and Streams APIs.

Compatibility: IE no, Edge 15 (partial), Chrome, FireFox, Safari 11, although compatibility with evolving features varies.

Use WebRTC adapter.js to smooth easy of use.

There's also the realted "Object RTC (ORTC) API" only on Edge, but I haven't looked into... @TODO ;)

Web Speech AP

Comprised of SpeechRecognition interface and SpeechSynthesis interface, which do exactly what you think they do.

Synthesis Compatibility: Experimental, but: IE no, Chrome, Edge 14, FireFox, Safari, although feature support varies

Recognition partially only in Chrome

SpeechRecognition depends on:

  • SpeechGrammarList (JSGF formatted set of words or phrases)

SpeechSynthesis uses:

  • SpeechSynthesisVoice interface that defines a "voice"
  • SpeechSynthesisUtterance interface that defines the words to say and how to say it

Synthesis


var synth = window.speechSynthesis;
var utterThis = new SpeechSynthesisUtterance("I'm sorry, Dave. I'm afraid I can't do that.");
utterThis.pitch = 0.6;
utterThis.rate = 0.9;
synth.speak(utterThis);
 

Recognition requires at least localhost (won't run directly pasted into browser).

Web Animations API

Allows direct access to the browser animation engine the underlies CSS Animations and Transitions, in a performant manner.

At its core, the animate method takes two params: keyframes and timing.

Compatibility: Chrome (partial), Firefox (partial), Edge no, Safari 13 (TP). There's a polyfill.


<div id="animate-me">Hello</div>
 

document.getElementById("animate-me").animate([
  { transform: 'rotate(180deg)' }, // 'translateX(0px)'
  { transform: 'rotate(-180deg)' } // 'translateY(-300px)'
], {
  duration: 5000,
  iterations: Infinity
});
 

WebXR API

"XR" is a term encompassing both Virtual Reality (VR) and Augmented Reality (AR)

The "spec" is highly experimental and still very much under development.

Depends somewhat on achieving 60fps, which is basically the standard for smooth animation*.

* Although VR works best with 90FPS+ to help avoid nausea.

Based on the now deprecated WebVR API that was used essentially only for demos, and had very experimental and specific mixed support of browsers/platforms/devices.

Compatibility is still mixed: Edge 15 ("Windows Mixed Reality" only), Firefox (Win only), Android Chrome (Google Daydream and Cardboard), Samsung Internet (Galaxy device/Gear only), Chrome (flag, and specific versions/devices)

Web Bluetooth API

"an API to discover and communicate with devices over the Bluetooth 4 wireless standard using the Generic Attribute Profile (GATT)."

Compatibility: non-standard and not even on a standards track, but Chrome (varies by OS) only.

There's so many more useful and interesting APIs:

History interface, Web Audio API, Ambient Light Events, Background Tasks API, Channel Messaging API & Broadcast Channel API, Clipboard API, Geolocation interface, Media Capture and Streams API, Intersection Observer API, Position interface, Page Visibility API, WebGL API, File Interface, Web Storage API, Touch interface, Navigator interface, Credential Management API, Web Crypto API (no, not cryptocurrency), Web Video Text Tracks Format (WebVTT), Gamepad API, Pointer Lock API, and more...

About Todd

Lead Drupal Developer at @meetmiles