Skip to content

JavaScript Web APIs

Mattscreative edited this page Feb 21, 2026 · 1 revision

JavaScript Web APIs Guide

Table of Contents


Introduction

Web APIs are interfaces provided by browsers that allow JavaScript to interact with browser features and hardware.


Navigator API

The Navigator object contains information about the browser.

// Basic info
console.log(navigator.userAgent);      // Browser string
console.log(navigator.platform);        // Platform
console.log(navigator.language);        // Browser language
console.log(navigator.languages);       // Preferred languages

// Connection info
console.log(navigator.onLine);         // Is online?
console.log(navigator.connection);     // Network connection info

// Device info
console.log(navigator.hardwareConcurrency);  // CPU cores
console.log(navigator.deviceMemory);         // RAM (if available)

// Cookies
console.log(navigator.cookieEnabled);  // Cookies enabled?

// Check features
console.log(navigator.javaEnabled());   // Java enabled?

// Service Workers
console.log(navigator.serviceWorker);  // ServiceWorkerContainer

Clipboard API

// Read from clipboard
async function readClipboard() {
    try {
        const text = await navigator.clipboard.readText();
        console.log('Clipboard:', text);
    } catch (err) {
        console.error('Failed to read:', err);
    }
}

// Write to clipboard
async function writeClipboard(text) {
    try {
        await navigator.clipboard.writeText(text);
        console.log('Copied!');
    } catch (err) {
        console.error('Failed to copy:', err);
    }
}

// Write HTML to clipboard
async function copyHTML(html) {
    const blob = new Blob([html], { type: 'text/html' });
    const textBlob = new Blob([html], { type: 'text/plain' });
    await navigator.clipboard.write([
        new ClipboardItem({
            'text/html': blob,
            'text/plain': textBlob
        })
    ]);
}

Online/Offline Events

// Listen for online/offline
window.addEventListener('online', () => {
    console.log('Back online!');
    // Sync data
});

window.addEventListener('offline', () => {
    console.log('Gone offline!');
    // Disable features that require network
});

Geolocation API

// Check if geolocation is available
if ('geolocation' in navigator) {
    // Get current position
    navigator.geolocation.getCurrentPosition(
        (position) => {
            console.log('Latitude:', position.coords.latitude);
            console.log('Longitude:', position.coords.longitude);
            console.log('Accuracy:', position.coords.accuracy, 'meters');
            console.log('Altitude:', position.coords.altitude);
            console.log('Speed:', position.coords.speed);
        },
        (error) => {
            console.error('Error:', error.message);
        },
        {
            enableHighAccuracy: true,
            timeout: 5000,
            maximumAge: 0  // Don't use cached position
        }
    );
    
    // Watch position (continuous)
    const watchId = navigator.geolocation.watchPosition(
        (position) => {
            console.log('New position:', position.coords.latitude, position.coords.longitude);
        },
        (error) => console.error(error),
        { enableHighAccuracy: true }
    );
    
    // Stop watching
    navigator.geolocation.clearWatch(watchId);
}

Notifications API

// Request permission
async function requestNotificationPermission() {
    if (!('Notification' in window)) {
        console.log('Notifications not supported');
        return;
    }
    
    const permission = await Notification.requestPermission();
    console.log('Permission:', permission);
}

// Show notification
function showNotification(title, options = {}) {
    if (Notification.permission === 'granted') {
        const notification = new Notification(title, {
            body: options.body || '',
            icon: options.icon || '/icon.png',
            badge: options.badge || '/badge.png',
            tag: options.tag || '',
            data: options.data,
            requireInteraction: options.requireInteraction || false,
            actions: options.actions || []
        });
        
        notification.onclick = () => {
            console.log('Notification clicked');
            window.focus();
            notification.close();
        };
        
        return notification;
    }
}

// Example usage
document.getElementById('notifyBtn').addEventListener('click', async () => {
    await requestNotificationPermission();
    showNotification('Hello!', { body: 'This is a notification' });
});

Web Workers

Web Workers run code in a background thread, keeping the main thread responsive.

Main Thread (main.js)

// Create worker
const worker = new Worker('worker.js');

// Send message to worker
worker.postMessage({ type: 'compute', data: [1, 2, 3, 4, 5] });

// Receive message from worker
worker.onmessage = (event) => {
    console.log('Result:', event.data);
};

// Handle errors
worker.onerror = (error) => {
    console.error('Worker error:', error.message);
};

// Terminate worker
worker.terminate();

Worker Thread (worker.js)

// Receive message from main thread
self.onmessage = (event) => {
    const { type, data } = event.data;
    
    if (type === 'compute') {
        // Do heavy computation
        const result = data.reduce((sum, n) => sum + n, 0);
        
        // Send result back
        postMessage(result);
    }
};

// Or use addEventListener
self.addEventListener('message', (event) => {
    // Handle message
});

// Post message to main thread
postMessage({ status: 'done' });

// Error handling
self.onerror = (error) => {
    console.error('Error in worker:', error);
};

// Import scripts
importScripts('script1.js', 'script2.js');

Shared Worker (shared-worker.js)

// Create shared worker
const sharedWorker = new SharedWorker('shared-worker.js');

sharedWorker.port.onmessage = (event) => {
    console.log('From shared worker:', event.data);
};

sharedWorker.port.start();
sharedWorker.port.postMessage('Hello from main thread!');

Intersection Observer

Detect when elements enter or leave the viewport.

// Create observer
const observer = new IntersectionObserver(
    (entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                console.log('Element is visible:', entry.target);
                // Load content, animate, etc.
            } else {
                console.log('Element is hidden:', entry.target);
            }
        });
    },
    {
        root: null,        // Use viewport
        rootMargin: '0px', // Margin around root
        threshold: 0.5     // Trigger when 50% visible
    }
);

// Observe element
const element = document.getElementById('lazy-image');
observer.observe(element);

// Stop observing
observer.unobserve(element);

// Disconnect observer
observer.disconnect();

Lazy Loading Images

const imageObserver = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            img.classList.remove('lazy');
            imageObserver.unobserve(img);
        }
    });
}, {
    rootMargin: '50px 0px',
    threshold: 0.01
});

document.querySelectorAll('img.lazy').forEach(img => {
    imageObserver.observe(img);
});

Resize Observer

// Create observer
const observer = new ResizeObserver((entries) => {
    entries.forEach(entry => {
        const { width, height } = entry.contentRect;
        console.log('Size changed:', width, 'x', height);
        
        // Can also access borderBoxSize, contentBoxSize
    });
});

// Observe element
const element = document.getElementById('container');
observer.observe(element);

// Observe multiple
observer.observe(document.querySelectorAll('.box'));

// Stop observing
observer.disconnect();

Beacon API

Send data to server reliably, even when page unloads.

// Send beacon
const data = JSON.stringify({ event: 'pageview', url: '/home' });
navigator.sendBeacon('/api/analytics', data);

// With Blob
const blob = new Blob([JSON.stringify({ data: 'example' })], { type: 'application/json' });
navigator.sendBeacon('/api/endpoint', blob);

// Use case: analytics on page unload
document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
        navigator.sendBeacon('/api/analytics', JSON.stringify({
            type: 'pagehide',
            url: window.location.href
        }));
    }
});

Fullscreen API

// Request fullscreen
function requestFullscreen(element) {
    if (element.requestFullscreen) {
        element.requestFullscreen();
    } else if (element.webkitRequestFullscreen) { // Safari
        element.webkitRequestFullscreen();
    } else if (element.msRequestFullscreen) { // IE11
        element.msRequestFullscreen();
    }
}

// Exit fullscreen
function exitFullscreen() {
    if (document.exitFullscreen) {
        document.exitFullscreen();
    } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
    }
}

// Check if fullscreen
function isFullscreen() {
    return !!(
        document.fullscreenElement ||
        document.webkitFullscreenElement ||
        document.msFullscreenElement
    );
}

// Listen for changes
document.addEventListener('fullscreenchange', () => {
    console.log('Fullscreen changed:', !!document.fullscreenElement);
});

// Toggle fullscreen
function toggleFullscreen(element) {
    if (isFullscreen()) {
        exitFullscreen();
    } else {
        requestFullscreen(element);
    }
}

Page Visibility API

Detect when page is visible, hidden, or minimized.

// Check current state
console.log(document.visibilityState);  // 'visible', 'hidden', 'prerender', 'unloaded'

// Listen for changes
document.addEventListener('visibilitychange', () => {
    console.log('Visibility changed:', document.visibilityState);
    
    if (document.hidden) {
        console.log('Page is hidden - pause animations, stop polls');
    } else {
        console.log('Page is visible - resume');
    }
});

// Practical use: stop polling when hidden
let pollInterval;

function startPolling() {
    pollInterval = setInterval(() => {
        // Fetch data
    }, 5000);
}

function stopPolling() {
    clearInterval(pollInterval);
}

document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
        stopPolling();
    } else {
        startPolling();
    }
});

Performance API

// Navigation timing
const [navigation] = performance.getEntriesByType('navigation');

console.log('Page load time:', navigation.loadEventEnd - navigation.fetchStart);
console.log('DNS lookup:', navigation.domainLookupEnd - navigation.domainLookupStart);
console.log('TCP connect:', navigation.connectEnd - navigation.connectStart);
console.log('Response:', navigation.responseEnd - navigation.responseStart);
console.log('DOM content:', navigation.domContentLoadedEventEnd - navigation.fetchStart);
console.log('Page render:', navigation.loadEventEnd - navigation.fetchStart);

// Resource timing
performance.getEntriesByType('resource').forEach(resource => {
    console.log(resource.name, resource.duration);
});

// Custom marks
performance.mark('start');

function doSomething() {
    performance.mark('end');
    performance.measure('doSomething', 'start', 'end');
}

// Clear marks
performance.clearMarks();
performance.clearMeasures();

User Timing API

// Mark specific points
performance.mark('pageStart');
performance.mark('scriptsLoaded');
performance.mark('pageComplete');

// Measure between marks
performance.measure('pageLoad', 'pageStart', 'pageComplete');

// Get measurements
const measures = performance.getEntriesByType('measure');
measures.forEach(measure => {
    console.log(measure.name, measure.duration);
});

Quick Reference

// Navigator
navigator.userAgent
navigator.onLine
navigator.language

// Geolocation
navigator.geolocation.getCurrentPosition(success, error, options)

// Clipboard
navigator.clipboard.readText()
navigator.clipboard.writeText(text)

// Notifications
Notification.requestPermission()
new Notification(title, options)

// Web Workers
new Worker(url)
worker.postMessage(data)
worker.onmessage = (e) => { }

// Intersection Observer
new IntersectionObserver(callback, options)
observer.observe(element)

// Performance
performance.now()
performance.mark(name)
performance.measure(name, startMark, endMark)

// Page Visibility
document.visibilityState
document.hidden

// Fullscreen
element.requestFullscreen()
document.exitFullscreen()
document.fullscreenElement

Clone this wiki locally