It isn’t uncommon for people to have multiple windows open (each with multiple tabs) while browsing the Internet. In fact, they may even have multiple browsers running. As web developers, we tend to do a lot of things when a page first loads—animations, starting videos, opening modals, starting slide shows, etc.
We know that when a page loads, and when it is actually viewed are not often the same event. For example, if a link to your site is opened to a new tab it could be minutes, hours, or even days until it is actually viewed.
This creates two problems. A good example of one of these problems is a video that you want to automatically play. This is very easy to do on page load, but if someone opens the page in another tab, they might not actually open the tab until the video is over.
The other problem this creates is when a page needs to make an AJAX request back to a server on a regular interval. If the page is open in an unused tab, a hidden window, or an inactive browser, it could result in a lot of unnecessary server requests. This was the exact issue I faced when working with Postmatic on their new live templating plugin, Epoch.
Every fifteen seconds, Epoch automatically counts the number of comments to make sure no new comments were added. If a new comment is discovered, Epoch takes it into account and then renders it. We were very worried about the effects of someone opening a post, reading it, and then leaving it open in an unused tab for a week. The solution to this problem turned out to be a just a few lines of code.
About the Visibility API
In older browsers, we could determine the active state of a tab by using jQuery’s blur method. This method, however, was pretty unreliable; not to mention, it simply doesn’t work in new browsers. Instead, a new Visibility API was introduced in 2011, which has a pretty good usability score. It does not include IE9 or earlier though.
The Visibility API tells you the current state of the page—whether it is rendering, visible, not visible, etc. While the implementation of the Visibility API is very widespread, it, of course, relies on vendor-specific prefixes. This is just further evidence that the people who make browsers are on a mission to drive us insane with vendor-specific prefixes.
Fortunately, there are a few wrappers for the Visibility API that make the prefixes invisible to us. In this article I will explain how to use Visibility.js by Andrey Sitnik. This wrapper is very easy to use, and is covered by the GPL-compatible MIT License, making it safe to use in your WordPress projects.
It can be added as a dependency to your project using all popular dependency management systems or loaded via a CDN. I will trust you to enqueue properly.
Using the Visibility Wrapper
In the next two sections, I’m going to show you two simple ways to implement the Visibility wrapper to solve both of the problems I discussed in the introduction to this article. I am going to show both examples in JavaScript only. Note: Please be sure to implement these into your plugin or theme the right way.
Example One: Autoplay a YouTube Video
YouTube provides an API for loading a video into an IFrame. It is pretty straight-forward. If you look at the example code, you will see that there is an event that runs when the video is loaded. In the callback function for that event, they show how to play the video. Here is what it looks like:
function onPlayerReady(event) { event.target.playVideo(); }
Using the Visibility.js wrapper, we can modify that function to not start the video until the page is visible with a very simple change:
function onPlayerReady(event) { Visibility.onVisible(function () { event.target.playVideo(); }); }
If the page is rendered in an active browser tab, the behaviour will be identical. On the other hand, if someone opens the page into an inactive tab, the video won’t start until that tab is active again.
The same strategy can be applied to several different situations. For example, if you are using a slider, you may wish to start the slideshow only when the page is actually visible.
Example Two: Enhanced Timing Functions
JavaScript provides a very simple way to repeat the same function on a set interval. Here is the most basic example:
setInterval( function() { console.log( 'snacks' ); }, 10000 );
This will log the word “snacks” to the console every ten seconds.
These types of timing functions are used to power auto-play sliders, but can also be used to make regular callbacks to a server to check for changes in data via AJAX. Often times, these sorts of regular “call home” checks are necessary in server configurations without a constant two-way client to server connection.
Now consider this timing function:
setInterval( function() { $.get( url, {action: "something" }, function( response) { //do something } ); }, 10000 );
It will make an AJAX request every ten seconds. That’s an extra six requests to your server per minute, per active viewer. If you need that kind of constant polling, that’s fine, but if someone opens the page, reads it for a five minutes, and then leaves the tab open but inactive for a day, that’s more than eight thousand unnecessary requests to your server.
While this is a problem that technologies like websockets solve very well, a WordPress plugin or theme developer cannot rely on websockets or a similar technology being used unless they are working on code for a specific site—where they know websockets are in use.
The same wrapper for the Visibility API that I discussed in the last step can also be used in place of setInterval, but will only run the callback function if the current tab is visible.
Here is the last example, refactored to only run if the current tab is visible:
Visibility.every( 10000, function () { $.get( url, {action: "something" }, function( response) { //do something } ); });
When the page is in a tab that is visible, it behaves exactly the same as when using setInterval. But, when the tab is not visible, nothing happens. The best part, besides the reduced resource use on both your server and your visitor’s computer, is that the callback function will run immediately upon the tab becoming visible.
More Optimization and More Control
As we build more and more interactive applications with WordPress, we will undoubtedly rely on two-way communication between client and server. Finding efficient ways to do so are very important. With this in mind, it is unsurprising to see that Automattic is a sponsor of Socket.io, an excellent node.js-based system for real-time communication between client and server.
For more traditional WordPress-usage, the Visibility API is an important tool for improving efficiency and usability of our plugins, themes, and apps. I have shown two simple examples that I hope you will find useful and will be able to adapt to your needs. More importantly, I hope that you will now be thinking of new ways to add two-way interactivity to your WordPress sites.
1 Comment