A presentation at DDD Brisbane in December 2022 in Brisbane QLD, Australia by Julian Burr
@jburr90 / Julian Burr DDD BRISBANE Yes, Your Browser Can do That! (Probably)
Why do Browser APIs matter? A very brief history of frontend development and the constant desire to build native
stopme.io The ultimate SaaS (Stopwatch as a Service) product for everyone stop me.io
01 Observe
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport const callback = (entries, observer) => { entries.forEach(entry => { // … }) } const observer = new IntersectionObserver( callback, options ) observer.observe(element) observer.unobserve(element)
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport const callback = (entries, observer) => { entries.forEach(entry => { // … }) } const observer = new IntersectionObserver( callback, options ) observer.observe(element) observer.unobserve(element)
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport const callback = (entries, observer) => { entries.forEach(entry => { // … }) } const observer = new IntersectionObserver( callback, options ) observer.observe(element) observer.unobserve(element)
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport const callback = (entries, observer) => { entries.forEach(entry => { // … }) } const observer = new IntersectionObserver( callback, options ) observer.observe(element) observer.unobserve(element)
01 Intersection Observer Keep track of when DOM elements enter or leave the users viewport
01 Resize Observer Observe DOM elements and run callbacks whenever their content box changes
01 Resize Observer Observe DOM elements and run callbacks whenever their content box changes const callback = (entries, observer) => { entries.forEach(entry => { // … }) } const observer = new ResizeObserver( callback, options ) observer.observe(element) observer.unobserve(element)
01 Resize Observer Observe DOM elements and run callbacks whenever their content box changes const callback = (entries, observer) => { entries.forEach(entry => { // … }) } const observer = new ResizeObserver( callback, options ) observer.observe(element) observer.unobserve(element)
01 Resize Observer Observe DOM elements and run callbacks whenever their content box changes
02 Even observe the user’s device
02 Page Visibility API Detect when the tab of the current page is active or in the background
02 Page Visibility API Detect when the tab of the current page is active or in the background
02 Page Visibility API Detect when the tab of the current page is active or in the background function handleChange () { if (document.visibilityState === “hidden”) { // do or stop something when tab is hidden } else { // do or stop something when it’s visible } } document.addEventListener( “visibilitychange”, handleChange )
02 Page Visibility API Detect when the tab of the current page is active or in the background
02 Network Information API Get information about the users network connection
02 Network Information API Get information about the users network connection
02 Network Information API Get information about the users network connection function handleChange () { // navigator.connection.effectiveType // *.type // *.downlink / *.downlinkMax // *.rtt // *.saveData if (!navigator.onLine) { // user is offline } } navigator.connection.addEventListener( “change”, handleChange );
02 Network Information API Get information about the users network connection function handleChange () { // navigator.connection.effectiveType // *.type // *.downlink / *.downlinkMax // *.rtt // *.saveData if (!navigator.onLine) { // user is offline } } navigator.connection.addEventListener( “change”, handleChange );
02 Network Information API Get information about the users network connection function handleChange () { // navigator.connection.effectiveType // *.type // *.downlink / *.downlinkMax // *.rtt // *.saveData if (!navigator.onLine) { // user is offline } } navigator.connection.addEventListener( “change”, handleChange );
02 Network Information API Get information about the users network connection function handleChange () { // navigator.connection.effectiveType // *.type // *.downlink / *.downlinkMax // *.rtt // *.saveData if (!navigator.onLine) { // user is offline } } navigator.connection.addEventListener( “change”, handleChange );
02 Network Information API Get information about the users network connection
02 Battery Status API Get details about the devices battery status
02 Battery Status API Get details about the devices battery status
02 Battery Status API Get details about the devices battery status const battery = await navigator.getBattery() function handleChange () { // battery.charging // *.level // *.chargingTime // *.dischargingTime } battery.addEventListener( “chargingchange” handleChange ) // “levelchange” // “chargingtimechange” // “dischargingtimechange”
02 Battery Status API Get details about the devices battery status const battery = await navigator.getBattery() function handleChange () { // battery.charging // *.level // *.chargingTime // *.dischargingTime } battery.addEventListener( “chargingchange” handleChange ) // “levelchange” // “chargingtimechange” // “dischargingtimechange”
02 Battery Status API Get details about the devices battery status const battery = await navigator.getBattery() function handleChange () { // battery.charging // *.level // *.chargingTime // *.dischargingTime } battery.addEventListener( “chargingchange” handleChange ) // “levelchange” // “chargingtimechange” // “dischargingtimechange”
02 Battery Status API Get details about the devices battery status const battery = await navigator.getBattery() function handleChange () { // battery.charging // *.level // *.chargingTime // *.dischargingTime } battery.addEventListener( “chargingchange” handleChange ) // “levelchange” // “chargingtimechange” // “dischargingtimechange”
02 Battery Status API Get details about the devices battery status
03 Enhance your Components
03 I18n API Internationalisation helpers and utilities
03 const options = { dateStyle: “full”, timeStyle: “long”, timeZone: “Australia/Sydney” }) new Intl.DateTimeFormat(“en-US”, options) .format(date) // Friday, December 2, 2022 at 12:21:40 PM // GMT+11 Intl API Internationalisation helpers and utilities
03 const options = { dateStyle: “full”, timeStyle: “long”, timeZone: “Australia/Sydney” }) new Intl.DateTimeFormat(“en-US”, options) .format(date) // Friday, December 2, 2022 at 12:21:40 PM // GMT+11 Intl Internationalisation helpers and utilities
03 const fmt = new Intl.RelativeTimeFormat( “en”, { style: “narrow” } ) fmt.format(3, “day”) // in 3 days fmt.format(-2, “year”) // 2 years ago intl API Internationalisation helpers and utilities
03 const formatter = new Intl.RelativeTimeFormat( “en”, { style: “narrow” } ) formatter.format(3, “day”) // in 3 days formatter.format(-2, “year”) // 2 years ago Intl API Internationalisation helpers and utilities
03 intl API Internationalisation helpers and utilities const au = new Intl.NumberFormat(“en-AU”) au.format(123_456.79); // 123,456.79 const de = new Intl.NumberFormat(“de-DE”) de.format(123_456.79); // 123.456,79
03 const fmt = new Intl.NumberFormat( “de-DE”, { style: “currency”, currency: “EUR” } ) fmt.format(123_456.79) // 123.456,79 € intl API Internationalisation helpers and utilities
03 const fmt = new Intl.NumberFormat(“en-AU”, { style: “unit”, unit: “liter”, unitDisplay: “long” }) fmt.format(123) // 123 litres Intl API Internationalisation helpers and utilities
03 const fmt = new Intl.NumberFormat(“en-AU”, { style: “unit”, unit: “liter”, unitDisplay: “long” }) fmt.format(123) // 123 litres intl API Internationalisation helpers and utilities
03 Screen Wake Lock API Let the users device know that you don’t want the screen to lock due to inactivity
03 Screen Wake Lock API Let the users device know that you don’t want the screen to lock due to inactivity try { const wakeLock = await navigator .wakeLock .request(“screen”) } catch (e) { // Request failed, e.g. for system // related reasons like low battery } wakeLock.release()
03 Screen Wake Lock API Let the users device know that you don’t want the screen to lock due to inactivity try { const wakeLock = await navigator .wakeLock .request(“screen”) } catch (e) { // Request failed, e.g. for system // related reasons like low battery } wakeLock.release()
03 Screen Wake Lock API Let the users device know that you don’t want the screen to lock due to inactivity try { const wakeLock = await navigator .wakeLock .request(“screen”) } catch (e) { // Request failed, e.g. for system // related reasons like low battery } wakeLock.release()
03 Screen Wake Lock API Let the users device know that you don’t want the screen to lock due to inactivity
03 EyeDropper API Allow your users to pick a colour from anywhere on their screen
03 EyeDropper API Allow your users to pick a colour from anywhere on their screen
03 EyeDropper API Allow your users to pick a colour from anywhere on their screen const eyeDropper = new EyeDropper() try { const result = await eyeDropper.open() // *.sRGBHex } catch (e) { // failure, also triggered when user // cancels }
03 EyeDropper API Allow your users to pick a colour from anywhere on their screen
04 Almost as good as native
04 Vibration API Control the devices vibration for haptic feedback
04 Vibration API Control the devices vibration for haptic feedback
04 Vibration API Control the devices vibration for haptic feedback navigator.vibrate(200) // Pattern navigator.vibrate([200, 100, 200])
04 Vibration API Control the devices vibration for haptic feedback // https://github.com/hjdesigner/vibration-api // Super Mario navigator.vibrate([ 87, 89, 104, 176, 96, 176, 88, 88, 79, 241, 176, 377, 191 ]) // Game of Thrones navigator.vibrate([ 950, 50, 530, 80, 100, 100, 100, 60, 930, 50, 530, 80, 100, 100, 100, 60, 980 ])
04 Vibration API Control the devices vibration for haptic feedback
04 Contact Picker API Let users select from their device contacts list with the native picker
04 Contact Picker API Let users select from their device contacts list with the native picker
04 Contact Picker API Let users select from their device contacts list with the native picker const supportedProperties = await navigator.contacts.getProperties() // [“name”, “email”, “tel”, “address”, “icon”] try { const props = [“name”, “email”] const options = { multiple: true } const contacts = await navigator .contacts .select(props, opts) } catch (e) { // Failure or cancellation }
04 Contact Picker API Let users select from their device contacts list with the native picker const supportedProperties = await navigator.contacts.getProperties() // [“name”, “email”, “tel”, “address”, “icon”] try { const props = [“name”, “email”] const options = { multiple: true } const contacts = await navigator .contacts .select(props, opts) } catch (e) { // Failure or cancellation }
04 Contact Picker API Let users select from their device contacts list with the native picker const supportedProperties = await navigator.contacts.getProperties() // [“name”, “email”, “tel”, “address”, “icon”] try { const props = [“name”, “email”] const options = { multiple: true } const contacts = await navigator .contacts .select(props, opts) } catch (e) { // Failure or cancellation }
Let users select from their device contacts list with the native picker Mobile Contact Picker API Desktop 04
04 Web Share API Allow users to share content through any of their installed apps using the native picker
04 Web Share API Allow users to share content through any of their installed apps using the native picker
04 Web Share API Allow users to share content through any of their installed apps using the native picker const shareData = { title: “stopme.io”, text: “The best SaaS product in the world”, url: “https://stopme.io” } // Must be triggered by user interaction btn.addEventListener(“click”, async () => { try { await navigator.share(shareData); } catch (e) { // failed or cancelled } });
04 Web Share API Allow users to share content through any of their installed apps using the native picker const shareData = { title: “stopme.io”, text: “The best SaaS product in the world”, url: “https://stopme.io” } // Must be triggered by user interaction btn.addEventListener(“click”, async () => { try { await navigator.share(shareData); } catch (e) { // failed or cancelled } });
04 Web Share API Allow users to share content through any of their installed apps using the native picker const shareData = { title: “stopme.io”, text: “The best SaaS product in the world”, url: “https://stopme.io” } // Must be triggered by user interaction btn.addEventListener(“click”, async () => { try { await navigator.share(shareData); } catch (e) { // failed or cancelled } });
04 Web Share API Allow users to share content through any of their installed apps using the native picker
End Honorable Mentions
End // Bluetooth API const devices = await navigator.bluetooth.getDevices() const device = await navigator.bluetooth .requestDevice({ filters: [{ services: [A, B] }] }) // USB API const devices = await navigator.usb.getDevices() Honorable Mentions const device = await navigator.usb. .requestDevice({ filters: [{ vendorId: id }] })
End // Geolocation API // Old but gold navigator.geolocation .getCurrentPosition(pos => { // pos.coords.latitude // *.coords.longitude }) const watchId = navigator.geolocation .watchPosition(pos => { // … }) navigator.geolocation.clearWatch(watchId) Honorable Mentions
End // File System Access API const options = { types: [ A, B ] } const [handle] = await window.showOpenFilePicker(options) const fileData = await handle.getFile() // Handling directories const dirHandle = await window.showDirectoryPicker() Honorable Mentions // Saving files const options = { types: [{ description: “Text file”, accept: { “text/plain”: [“.txt”] }, }] } await window.showSaveFilePicker(options)
End Honorable Mentions // Clipboard API await navigator.clipboard.writeText(txt) const text = await navigator.clipboard.readText()
End // Presentation API const urls = [ presentationUrl, altUrl ] const request = new PresentationRequest(urls) const availability = await request.getAvailability() availability.onchange = () => { // availability.value }) const connection = await request.start() connection.close() Honorable Mentions
End // Web Speech API // Recognition const recognition = new SpeechRecognition() recognition.start() recognition.onresult = (event) => { const word = event.results[0][0].transcript // event.results[0][0].confidence }) Honorable Mentions // Synthesis const synth = window.speechSynthesis const words = new SpeechSynthesisUtterance(txt) synth.speak(words)
End Honorable Mentions // And soo many more… // Check out: // https://developer.mozilla.org/enUS/docs/Web/API
Thanks! @jburr90 / julian burr https://www.julianburr.de/ ddd-brisbane-2022-slides.pdf