The CSS Font Loading API provides events and interfaces for dynamically loading font resources. Browser Support: Chrome (35+), Firefox (41+), Safari (10+)
const roboto = new FontFace('Roboto', 'url(roboto.woff2)');
const addLoadedClass = (font) => {
document.body.classList.add(`${font.family.toLowerCase()}-loaded`);
}
roboto.load();
document.fonts.add(roboto);
document.fonts.ready.then(() => console.log(`${document.fonts.size} FontFaces loaded.`));
roboto.loaded.then(addLoadedClass);
Custom Elements is a capability for creating your own custom HTML tags and elements. They can have their own scripted behavior and CSS styling. They are part of Web Components but they can also be used by themselves. Browser Support: Chrome Canary (54+)
class CustomElement extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
const t = document.querySelector('template');
const instance = t.content.cloneNode(true);
shadowRoot.appendChild(instance);
}
static get observedAttributes() {
return ['disabled'];
}
connectedCallback() {}
disconnectedCallback() {}
attributeChangedCallback(attrName, oldVal, newVal) {}
}
customElements.define('custom-element', CustomElement);
customElements.whenDefined('custom-element').then(() => {});
The Web Bluetooth API is an interface to discover and communicate with devices over the Bluetooth 4 wireless standard using the Generic Attribute Profile (GATT). Browser Support: Chrome Canary (55+)
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('battery_service'))
.then(service => service.getCharacteristics())
.then(characteristic => characteristic.readValue())
.then(value => console.log(`Battery level is ${value}%`))
.catch(error => console.error(error));
The Gamepad API introduces new events on the Window object for reading gamepad and controller state. Browser Support: Chrome (21+), Firefox (29+), Edge (12+)
let gamepadIndex;
let loopID;
window.addEventListener('gamepadconnected', (e) => {
gamepadIndex = e.gamepad.index;
loopID = window.requestAnimationFrame(gameLoop);
});
window.addEventListener('gamepaddisconnected', (e) => {
gamepadIndex = null;
window.cancelAnimationFrame(loopID);
});
const BUTTON_LEFT_INDEX = 14;
const BUTTON_RIGHT_INDEX = 15;
function gameLoop() {
let gamepads = navigator.getGamepads();
let gp = gamepads[gamepadIndex];
let button = gp.buttons[0].pressed;
switch (button) {
case BUTTON_LEFT_INDEX:
turnLeft();
break;
case BUTTON_RIGHT_INDEX:
turnRight();
break;
default:
fly();
}
window.requestAnimationFrame(gameLoop);
}