@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