Every once in a while, writing and testing code can be a little like arm wrestling or maybe even like pulling teeth. Things can be going along smooth as silk and then all of a sudden you hit a requirement that, on the surface at least, seems easy enough. But, as you dive into its construction, it turns out to be difficult and time consuming to find just the right combination of plugins, extensions, or algorithms that work, especially when executing them through Ajax callbacks.
Such is the case for a problem solved for Southern Home Design Plans, a site for selling custom home designs, owned and operated by a very talented architectural firm in Cary, North Carolina. The site is built with a highly customized Genesis Framework child theme and WooCommerce.
The WooCommerce shop page is highly customized. In fact, when you see it, you wouldn't even know that it's WooCommerce because other than displaying 3 house plans per row, there is no further resemblance to anything WooCommerce vanilla. The first requirement for the catalog page is to display all the house plans using infinite scroll for pagination. As you know, infinite scroll works by invoking an Ajax script when a user scrolls to the bottom of the page. The Ajax routine loads new products and extends the size of the page.
To satisfy this requirement, we used the very popular Animated Infinite Scroll plugin available from Code Canyon. The plugin is easy enough to setup and it works like a charm. And SBThemes, the author, provides great support.
The second requirement, also known as the better half of this challenge, is making sure the custom image areas are all the same size per each row. To visualize what I mean, look at the following image from the development site. (This is still a work in progress so please don't be too critical.)
The width of these images is 332px. As you can see, their heights are very different. This is the nature of house plans. When you drive down the street or walk through your neighborhood, the homes may appear to be similar in width or design, but their heights can be very different. The requirement is to keep the appearance of the catalog images consistent so each product in a catalog row presents with the same height. The rows have to be even.
To accommodate this, the image is wrapped in a parent div:
To make certain that the parent container is the same height within each row, we use the jQuery MatchHeight.js extension. This extension calculates the height of each parent div after the images load and adjusts them to the same height if necessary. It does a great job and is fairly easy to use.
As well as these two tools work individually, getting them to work together in concert proves challenging. This is directly related to how Ajax works in browsers. We've discussed this before in a previous post, Formidable Pro: Invoke Ajax on Submit, so we won't repeat the details here. But in summary, the problem boils down to a timing issue. The Ajax callback in the Animated Infinite Scroll plugin executes the matchHeight function before all of the images load. This results in an uneven page.
The solution to this problem requires holding back on the matchHeight function until all the images load. But how do we do that? Some recommendations suggest using the jQuery(window).load() function. This sounds like a great idea except that the page will often load before all images have been downloaded. Again, this results in incomplete results and an uneven page.
The first thing we tried is the jQuery waitForImages extension. After spending several hours trying every conceivable combination of parameters, this plugin just won't work in the Ajax callback. The results were always the same. The rows were never completely balanced.
Then we tried the jQuery ImagesLoaded extension. There are two versions of this extension, the first is very simple jQuery code written by Paul Irish in 2010. The second is a much more complex version by David DeSandro that is still being maintained. Both of these versions work well to allow Animated Infinite Scroll and jQuery MatchHeight.js to work in concert.
If you're interested, the code used in the On Pagination End callback is: