Fix Jetpack Infinite Scroll + Masonry Layout Bug

Recently, I’ve played with Jetpack Infinite Scroll Feature on a Masonry grid. It’s quite frustrating to make the Jetpack Infinite Scroll work correctly on Masonry after the event of the load post being triggered.

I’ve stumble upon Devin Price’s solution in here http://wptheming.com/2013/04/jetpack-infinite-scroll-masonry/ using the second method since Desandro recommends using the appended method in his docs.

jQuery( document ).ready( function( $ ) {
     infinite_count = 0;
     // Triggers re-layout on infinite scroll
     $( document.body ).on( 'post-load', function () {
	infinite_count = infinite_count + 1;
	var $container = $('#content');
	var $selector = $('#infinite-view-' + infinite_count);
	var $elements = $selector.find('.hentry');
	$elements.hide();
	$container.masonry( 'reload' );
	$elements.fadeIn();
     });
});

Jetpack doesn’t pass the new elements in the post-load event, but does append a new div .infinite-wrap with a unique id #infinite-view-1. So, the solution is to you keep track of how many times the event has fired by using the infinite_count variable.

infinite_count = infinite_count + 1;

It’s working fine, except there is one glitch that can cause the Masonry layout to break, which is when the infinte_count miss matched the count with the actual Jetpack Infinite Scroll count. This happened to me many time when I try to scroll the windows before the Jetpack Infinite Scroll finished pulling the post, the infinite_count is increasing while Jetpack Infinite Scroll still pulling the first one and resulted in inconsistent layout due to failed to append the element in .infinite-wrap div to the grid container.

So, I’ve come will more simple idea on how to get the element inside .infinite_wrap without using infinte_count variable. Here is my solution:

var $container;

function nsc_trigger_masonry() {
    // don't proceed if $grid has not been selected
    if ( !$container ) {
        return;
    }
    // init Masonry
    $container.imagesLoaded(function(){
        $container.masonry({
            // options
            itemSelector: '.article-list',
            columnWidth: '.small-box',
            percentPosition: true,
            gutter: 0,
        });
    });
}

$(window).load(function(){
    $container = $('.article-row'); // this is the grid container

    nsc_trigger_masonry();

    // Triggers re-layout on infinite scroll
    $( document.body ).on( 'post-load', function () {
        
        // I removed the infinite_count code
        var $selector = $('.infinite-wrap');
        var $elements = $selector.find('.article-list');
        
        /* here is the idea which is to catch the selector whether it contain element or not, if it's move it to the masonry grid. */
        if( $selector.children().length > 0 ) {
            $container.append( $elements ).masonry( 'appended', $elements, true );
            nsc_trigger_masonry();
        }
        
    });
});

The idea is to check whether the div .infinite-wrap contain any element / children. if it’s move it to the masonry container.

Leave a Reply

Your email address will not be published. Required fields are marked *