Update on March 08, 2018: An updated tutorial covering the case of user scroll as the trigger to fade in the subsequent set of posts is here.
This article is based on Bill Erickson’s excellent tutorial titled Infinite Scroll in WordPress.
We shall add a Load More button below posts on Posts page and Archives in Genesis which when clicked, loads the next set of Posts below the current ones on the page without using a plugin like Jetpack’s infinite scroll module.
Quoting Bill,
The problem with the Jetpack infinite scroll (and other plugins like it) is they have to work with every theme so use a pretty hacky approach. They actually load the next page (like clicking the âNextâ link in your pagination), then pick out just the posts in the content area and insert that. Youâre loading a whole page when it would be more efficient to only load the posts required.
It can also cause issues with ad networks since youâre inflating your pageviews. Infinite scroll is a âpageviewâ when Jetpack loads the page to grab the posts, but the ad shown on that page isnât seen by an actual human.
Finally, with that tool youâre limited to only archive pages since they have the âNextâ button Jetpack can press. The approach described above can be used in any instance. When youâre on a single post you can load excerpts of other posts, like Iâve done on Pinch of Yum.
To understand how the solution works, head over to Bill’s article.
I’ve added in a line of logic to ensure that Load More button does not appear when the last set of results is shown.
Step 1
Create a file named load-more.js in child theme’s js
directory having the following:
jQuery(function($){ | |
// $('.post-listing').append( '<button class="load-more">Load More</button>' ); | |
// var button = $('.post-listing .load-more'); | |
var page = 2; | |
var loading = false; | |
$('body').on('click', '.load-more', function(){ | |
if( ! loading ) { | |
loading = true; | |
$(this).remove(); | |
var data = { | |
action: 'be_ajax_load_more', | |
page: page, | |
query: beloadmore.query, | |
}; | |
$.post(beloadmore.url, data, function(res) { | |
if( res.success) { | |
$('.post-listing').append( res.data ); | |
// $('.post-listing').hide().append( res.data ).fadeIn(500); // to have fadeIn effect | |
// $('.post-listing').append( button ); | |
page = page + 1; | |
loading = false; | |
} else { | |
// console.log(res); | |
} | |
}).fail(function(xhr, textStatus, e) { | |
// console.log(xhr.responseText); | |
}); | |
} | |
}); | |
}); |
Step 2
Create a file named say, template_load-more.php in the child theme having the following:
<?php | |
/** | |
* Javascript for Load More | |
* | |
*/ | |
function be_load_more_js() { | |
global $wp_query; | |
$args = array( | |
'url' => admin_url( 'admin-ajax.php' ), | |
'query' => $wp_query->query | |
); | |
wp_enqueue_script( 'be-load-more', get_stylesheet_directory_uri() . '/js/load-more.js', array( 'jquery' ), '1.0', true ); | |
wp_localize_script( 'be-load-more', 'beloadmore', $args ); | |
} | |
add_action( 'wp_enqueue_scripts', 'be_load_more_js' ); | |
add_action( 'genesis_before_loop', 'sk_opening', 20 ); // a high priority of 20 to make this appear below .archive-description | |
function sk_opening() { | |
echo '<div class="post-listing">'; | |
} | |
add_action( 'genesis_after_loop', 'sk_closing' ); | |
function sk_closing() { | |
// echo '</div>'; | |
echo '<button class="load-more">Load More</button></div>'; | |
} | |
// Remove Archive Pagination | |
remove_action( 'genesis_after_endwhile', 'genesis_posts_nav' ); | |
genesis(); |
Step 3
Add the following in child theme’s functions.php:
/** | |
* AJAX Load More | |
* @link http://www.billerickson.net/infinite-scroll-in-wordpress | |
*/ | |
function be_ajax_load_more() { | |
$args = isset( $_POST['query'] ) ? array_map( 'esc_attr', $_POST['query'] ) : array(); | |
$args['post_type'] = isset( $args['post_type'] ) ? esc_attr( $args['post_type'] ) : 'post'; | |
$args['paged'] = esc_attr( $_POST['page'] ); | |
$args['post_status'] = 'publish'; | |
ob_start(); | |
$loop = new WP_Query( $args ); | |
if( $loop->have_posts() ): while( $loop->have_posts() ): $loop->the_post(); | |
printf( '<article %s>', genesis_attr( 'entry' ) ); | |
do_action( 'genesis_entry_header' ); | |
do_action( 'genesis_before_entry_content' ); | |
printf( '<div %s>', genesis_attr( 'entry-content' ) ); | |
do_action( 'genesis_entry_content' ); | |
echo '</div>'; | |
do_action( 'genesis_after_entry_content' ); | |
do_action( 'genesis_entry_footer' ); | |
echo '</article>'; | |
// endwhile; endif; wp_reset_postdata(); | |
endwhile; if ( $_POST['page'] < $loop->max_num_pages ) { echo '<button class="load-more">Load More</button>'; } endif; wp_reset_postdata(); | |
$data = ob_get_clean(); | |
wp_send_json_success( $data ); | |
wp_die(); | |
} | |
add_action( 'wp_ajax_be_ajax_load_more', 'be_ajax_load_more' ); | |
add_action( 'wp_ajax_nopriv_be_ajax_load_more', 'be_ajax_load_more' ); | |
/** | |
* Template Redirect | |
* Use template_load-more.php for Posts page and all archives. | |
*/ | |
add_filter( 'template_include', 'custom_blog_archives_template', 99 ); | |
function custom_blog_archives_template( $template ) { | |
if ( is_home() || is_archive() ) { | |
$new_template = locate_template( array( 'template_load-more.php' ) ); | |
if ( '' != $new_template ) { | |
return $new_template ; | |
} | |
} | |
return $template; | |
} |
Warning: Use of Template Redirect as per the above code block will render home.php, archive.php, category.php and any other files that honour the WordPress template hierarchy (if present) ineffective. If usage of such templates is necessary, consider using get_template_part() to include the code of template_load-more.php in those individual files.
Step 4
Add the following in child theme’s style.css:
.post-listing { | |
margin-bottom: 40px; | |
} | |
.load-more { | |
display: table; | |
margin: 0 auto; | |
} |
References:
genesis/lib/structure/loops.php
Wonderful Tutorial. Sridhar, Can you please guide me how can i use ajax on pages where i have customized page templates. Like i have page template front-page.php which is widgetized and last widget is displaying posts only in blog manner. How can i put ajax underneath it. Thanks
Give this plugin a try: https://wordpress.org/plugins/ajax-load-more/
To tighten up Step 3, you can pass your args directly to `genesis_custom_loop()`. This way it still gets the layout of the standard loop that Genesis uses but with the custom arguments applied to WP_Query:
“`
<?php
$args = array(
// Query arguments here
);
ob_start();
genesis_custom_loop( $args );
if ( $_POST['page'] max_num_pages ) { echo ‘Load More’; } endif; wp_reset_postdata();
$data = ob_get_clean();
// And so on…
?>
“`
If you require a custom entry layoutâmaybe to remove things like the archive description that comes with the loopâthen you can add the appropriate hooks and filters just before you run `genesis_custom_loop()`.
Hi Eji, Thanks for the tip. Can you provide me any example, so that i can work on it. or a simple gist will work. Thanks a lot.
Regards,
Jazib
Is it possible to apply this load more button solution to the Front page if you’re using your front (home) page to show your latest posts and do not have a blog Posts page set? Thanks, Sridhar!
The
endwhile; if ( $_POST[‘page’] max_num_pages ) { echo ‘Load More’; } endif; wp_reset_postdata();
should be:
endwhile;
if ( $loop->max_num_pages > $_POST[‘page’] ) {
echo ‘Load More’;
}
endif;
Otherwise it keeps showing the button even if there are no more posts.
See: http://www.billerickson.net/infinite-scroll-in-wordpress/#comment-673977
Awesome tutorial Sridhar.
One question for you. How would you modify the load-more.js for the scrolling version that Bill had spoken about first.
I tried your code with Bill’s version for scrolling. It looks very similar, however it doesn’t work. Any ideas on how to fix this?
Works like a charm, much appreciated!
How would you use get_template_part() if I’d need to include the load more in a special category page template?
Would be great if you could epxlain that a bit further!
Nice one. Genesis has been tricky for me when making modifications or adding functionality.
In the past I used Ajax Load More(https://wordpress.org/plugins/ajax-load-more/) plugin for this but they don’t have a Genesis example so this article was perfect.
thanks.
Thank you Sridhar (and Bill) – an infinite solution that finally works for me.
Cheers, Rob
[…] you are looking for a button click trigger variation, follow this […]