Using Jetpack Infinite Scroll & Isotope (Masonry).
I am facing an issue where after every new ajaxed set of posts, I need to destroy
and then build
isotope layout. If I don’t go with this approach the new set of posts loaded by infinite scroll each time are not treated by isotope layout as its own and they miss on isotope styling. So, I need to rebuild isotope every time on post-load
trigger of infinite scroll.
This approach actually leaves the user with a flick effect and scrolls to the beginning of isotope layout.
//In functions.php
function vg_infinite_scroll_init() {
add_theme_support( 'infinite-scroll', array(
'container' => 'row-wrap',
'type' => 'scroll',
'render' => 'loop_p_arch_infinite_scroll_render',
'footer' => false,
'footer_widgets' => false,
'wrapper' => false,
'posts_per_page' => 9,
) );
}
add_action( 'after_setup_theme', 'vg_infinite_scroll_init' );
function loop_p_arch_infinite_scroll_render() {
while( have_posts() ) {
the_post();
get_template_part( 'content', 'product' );
}
}
function vg_get_prod_arch_posts( $post_type="post" ) {
$prodarch_posts = get_posts( array(
'numberposts' => 9,
'paged' => get_query_var( 'paged' ),
'post_type' => $post_type
) );
return $prodarch_posts;
}
// In archive-product.php
<!-- Isotope Grid -->
<section id="product_list">
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="grid" id="row-wrap">
<div class="grid-sizer"></div>
<?php
$products = vg_get_prod_arch_posts( 'product' );
if ( ! empty( $products ) ) {
foreach ( $products as $product ) {
setup_postdata( $GLOBALS['post'] = $product );
get_template_part( 'content', 'product' );
}
wp_reset_postdata();
}
?>
</div>
</div>
</div>
</div>
</section>
//In content-product.php
global $post;
?>
<div class="grid-item post product">
<div class="item_content">
<a href="#">
<div class="item_name">
<h4><?php the_title(); ?> </h4>
</div>
<?php echo get_the_post_thumbnail( $post->ID, 'large', array( 'class' => 'image_width_set' ) ); ?>
</a>
</div>
</div>
//In JS file
jQuery(document).on("post-load", function(e) {
jQuery('.grid').isotope('destroy');
jQuery('.grid').isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer',
gutter: 5
}
});
});
jQuery(window).load(function(){
jQuery('.grid').imagesLoaded(function() {
jQuery('.grid').isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer',
gutter: 5
}
});
})
})
1 Answer
Usually isotope allows appending new items and then just re-layout the masonry again:
Somewhere in your JS file you should put the elements you want to append into a variable, e.g. new_elements
jQuery('.grid').append(new_elements)
.isotope('appended', new_elements)
.imagesLoaded( function() {
jQuery('.grid').istotope('layout');
});
Source: http://isotope.metafizzy.co/methods.html
The solution
Thanks to @vajrasar for the final touches.
When you echo the Grid-Page Loop, add the following:
function loop_p_arch_infinite_scroll_render() {
$paged = get_query_var( 'paged', 1 );
?>
<div id="page-<?=$paged?>">
<?php while( have_posts() ) {
the_post();
get_template_part( 'content', 'product' );
}
?>
</div>
<script id="script-page-<?=$paged?>">
jQuery('document').ready(function($) {
var new_elements = $('#page-<?=$paged?>').children('.grid-item');
$('.grid')
.append(new_elements)
.isotope('appended', new_elements)
.imagesLoaded( function() {
$('.grid').isotope('layout');
});
$('#page-<?=$paged?>, #script-page-<?=$paged?>').remove();
});
</script>
<?php
}