Observing Your Web App - A Quick Round Up

December 30, 2018  |   5 min read

As web developers we write a lot of code to detect changes in our web app and do manipulations based on those changes. Today, the web has lots of APIs for “observing” your web app for many types of changes and letting you perform actions based on them.

Here’s a quick round up-

1. Observing the DOM through event listeners

The most classic way to detect changes by using addEventListener. This can be used to listen to native as well and custom events.

window.addEventListener('scroll', e => { ... });  // user scrolls the page.

el.addEventListener('focus', e => { ... });  // el is focused.

img.addEventListener('load', e => { ... });  // img is done loading.

el.addEventListener('custom-event', e => { ... });  // catch custom event fired on el.

2. Check for DOM tree modifications

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree.

const target = document.querySelector('#div_id');
 
const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
        console.log(mutation.type);
    });
});
 
const config = {
    attributes: true, 
    childList: true, 
    characterData: true 
} 
observer.observe(target, config);

3. Check when an element comes into view

The Intersection Observer API provides an easy way to watch and register callbacks to trigger when elements on a page come into view.

const images = document.querySelectorAll('.animate');

observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.intersectionRatio > 0) {
      console.log('in the view');
    } else {
      console.log('out of view');
    }
  });
});

images.forEach(image => {
  observer.observe(image);
});

Using this API we can trigger animations, lazy load images etc., when they come into view.


4. Check when the elements in DOM are re-sized

The ResizeObserver allows for elements to be notified when their size changes.

const myObserver = new ResizeObserver(entries => {
  entries.forEach(entry => {
    console.log('width', entry.contentRect.width);
    console.log('height', entry.contentRect.height);
  });
});

const el = document.querySelector('.some-element');
myObserver.observe(el);

With each entry, we get an object with properties - contentRect and target. The target is the DOM element itself, and contentRect is an object with the following properties: width, height, x, y, top, bottom, left and right.


5. Check if your web app is on full-screen mode

Using the Fullscreen API makes this possible.

var el = document.getElementById("myvideo");
if (el.requestFullscreen) {
  el.requestFullscreen();
}

Not just detection of full-screen mode but this API also allows the turning off and on of full-screen mode.


6. Check if the tab is in focus

document.addEventListener('visibilitychange', e => {
    if(document.hidden) {
        // .... do something
    } else {
        // .... dome something else
    }
});

I am still including this in the list even if this is not a new API but rather a technique. One use case can be to draw user attention back to the abandoned tab.


7. Check for device orientation changes

The Screen Orientation API makes this possible.

window.addEventListener('orientationchange', e => {
  console.log(screen.orientation.angle, screen.orientatio.type)
});

We can also check to see if the current orientation matches to a particular orientation.

const media = window.matchMedia('(orientation: portrait)');
media.addListener(mql => console.log(mql.matches));

8. Check for network status and changes

The Network Information API provides information about user’s network connection. Using this information it’s possible to conditionally load images, videos, fonts and other resources.

navigator.connection.addEventListener('change', e => {
  console.log(navigator.connection.effectiveType, navigator.connection.downlink);
});

Apart from properties effectiveType and downlink mentioned above, it also provides downlinkMax, rtt, saveData, type.


9. Check status of the device battery

This is possible using the Battery Status API.

navigator.getBattery().then(battery => {
  console.log(
    battery.level * 100 + '%',
    battery.charging,
    battery.chargingTime,
    battery.dischargingTime
    ); 
});

10. Check when your web app uses a deprecated API or hits a browser intervention

The Reporting API makes it possible

const observer = new ReportingObserver((reports, observer) => {
  reports.map(report => {
    console.log(report);
    // ..... send report to analytics etc..
  });
}, {buffered: true});

observer.observe();

I believe, currently, the ReportingObserver has only been shipped in latest Chrome.


11. Check the performance of you web app

The [PerformanceObserver] (https://developers.google.com/web/updates/2016/06/performance-observer) interface is used to observe performance measurement events and be notified of new performance entries as they are recorded in the browser’s performance timeline.

const observer = new window.PerformanceObserver(list => {
    list.getEntries().forEach(({name, startTime}) => {
        console.log({name, startTime});
    });
});
observer.observe({
    entryTypes: [{'paint', 'resource', 'mark', 'measure'}]
});

It’s really amazing that the web has so many great APIs at our disposal. Using these we can create web apps with better performance and greater user experience.

Note: Always check the browser support before using the modern APIs.


Useful Resources

  1. Watch the Best web features of 2018 face-off against each other
  2. Lazy Loading Images for Performance Using Intersection Observer
  3. Use Network Information API to Improve Responsive Websites
  4. ResizeObserver Sample
  5. PerformanceObserver and Paint Timing API