Single Posts
Developer documentation for the Ajax Load More Single Posts add-on.
Theme Templates
Some themes are more complicated than others with regards to implementing infinite scroll on single post templates.
To help you get started, we’re compiling a library of single.php examples for some popular WordPress themes and frameworks.
GeneratePress is a free WordPress theme that focuses on speed and usability.
Out of the box, the GeneratePress single.php template is pretty close to what we need. All that is required is to wrap the #primary div and add the Ajax Load More code as described in the Single Posts Implementation Guide.
<?php
/**
* The Template for displaying all single posts.
*
* @package GeneratePress
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
get_header(); ?>
<div id="alm-post-wrap">
<div id="primary" <?php generate_do_element_classes( 'content' ); ?>>
<main id="main" <?php generate_do_element_classes( 'main' ); ?>>
<?php
/**
* generate_before_main_content hook.
*
* @since 0.1
*/
do_action( 'generate_before_main_content' );
while ( have_posts() ) : the_post();
get_template_part( 'content', 'single' );
// If comments are open or we have at least one comment, load up the comment template.
if ( comments_open() || '0' != get_comments_number() ) :
/**
* generate_before_comments_container hook.
*
* @since 2.1
*/
do_action( 'generate_before_comments_container' );
?>
<div class="comments-area">
<?php comments_template(); ?>
</div>
<?php
endif;
endwhile;
/**
* generate_after_main_content hook.
*
* @since 0.1
*/
do_action( 'generate_after_main_content' );
?>
</main><!-- #main -->
</div><!-- #primary -->
<?php
/**
* generate_after_primary_content_area hook.
*
* @since 2.0
*/
do_action( 'generate_after_primary_content_area' );
generate_construct_sidebars();
?>
</div>
<style>
/* Inline style to help with CSS float issues */
.alm-single-post{
overflow: hidden;
}
</style>
<?php
if( function_exists( 'alm_render' ) ){
// Ajax Load More
$args = [
'single_post' => 'true',
'single_post_id' => get_the_ID(),
'single_post_target' => '#alm-post-wrap',
'post_type' => 'post',
'pause_override' => 'true',
];
alm_render($args);
}
get_footer(); ?>
PHPThe default Genesis single.php template includes only one function, genesis(). This doesn’t work with Ajax Load More so we need to extend the template to include the default Genesis actions, hooks and a wrapping div element.
Below is a modified single.php Genesis template developed specifically for implementation with Ajax Load More.
<?php
get_header();
?>
<div id="alm-post-wrap">
<?php
/**
* Fires after the header, before the content sidebar wrap.
*
* @since 1.0.0
*/
do_action( 'genesis_before_content_sidebar_wrap' );
genesis_markup(
[
'open' => '<div %s>',
'context' => 'content-sidebar-wrap',
]
);
/**
* Fires before the content, after the content sidebar wrap opening markup.
*
* @since 1.0.0
*/
do_action( 'genesis_before_content' );
genesis_markup(
[
'open' => '<main %s>',
'context' => 'content',
]
);
/**
* Fires before the loop hook, after the main content opening markup.
*
* @since 1.0.0
*/
do_action( 'genesis_before_loop' );
/**
* Fires to display the loop contents.
*
* @since 1.1.0
*/
do_action( 'genesis_loop' );
/**
* Fires after the loop hook, before the main content closing markup.
*
* @since 1.0.0
*/
do_action( 'genesis_after_loop' );
genesis_markup(
[
'close' => '</main>', // End .content.
'context' => 'content',
]
);
/**
* Fires after the content, before the main content sidebar wrap closing markup.
*
* @since 1.0.0
*/
do_action( 'genesis_after_content' );
genesis_markup(
[
'close' => '</div>',
'context' => 'content-sidebar-wrap',
]
);
/**
* Fires before the footer, after the content sidebar wrap.
*
* @since 1.0.0
*/
do_action( 'genesis_after_content_sidebar_wrap' );
?>
</div>
<style>
/* Inline style to help with CSS float issues */
#alm-post-wrap{
display: block;
overflow: hidden;
}
.alm-single-post {
overflow: hidden;
}
</style>
<?php
if( function_exists( 'alm_render' ) ){
// Ajax Load More
$args = [
'single_post' => 'true',
'single_post_id' => get_the_ID(),
'single_post_target' => '#alm-post-wrap',
'single_post_order' => 'previous',
'post_type' => 'post',
'pause_override' => 'true',
];
alm_render($args);
}
get_footer();
?>
PHPNote: You should always create a Child Theme before modifying core theme templates.
Callback Functions
almSinglePostsLoaded
The almSinglePostsLoaded() callback is dispatched after Single Posts has completed its initial setup routine on page load.
window.almSinglePostsLoaded = function (alm) {
console.log( 'ALM Single Posts Loaded' );
}
JavaScriptFrequently Asked Questions
Below are common questions regarding the Single Posts add-on. If you have a question and don’t see an answer here, please visit the support page and submit your request.
When using Single Posts the pause parameter is automatically set to true, this stops ALM from loading posts on initial page load. The enable scrolling to trigger an Ajax load you need to set pause_override to true.
Example Shortcode[ajax_load_more single_post="true" single_post_target="#post-wrapper" pause_override="true"]
The following code will render content only when loaded via the single post Ajax request.
if ( isset( $_GET ) && $_GET[ 'alm_page'] ) ) {
echo '<p>I am only displayed when loaded via Ajax</p>';
}
PHPThis is possible because Ajax Load More appends querystring parameters to each request for identification purposes.
If you are having trouble displaying your comments template on the posts loaded via Ajax try adding the following $withcomments code above the call your function call to comments_template().
<?php
// Display comments template in Ajax request
global $withcomments;
$withcomments = true;
comments_template();
?>
PHPAny content element that requires JavaScript and has been loaded dynamically (with Ajax) will most likely need to be initiated after a successful Ajax request.
Examples of content that may require JavaScript initiation are:
- Social sharing plugins
- Facebook Comments
- Disqus Comments
- Slideshows
- Lightbox Galleries
- etc…
Have a look at the almComplete() callback function. This callback is triggered after every successful Ajax Load More query and will allow you initiate functionality as content is loaded.
If shortcodes are rendering as static text and not parsing in ajax loaded posts you may need to run a filter in your repeater template on the_content()
function.
<?php
$postid = get_the_ID();
$content = do_shortcode(get_post_field( 'post_content', $postid ));
$content = apply_filters('the_content', $content);
echo $content;
?>
PHPVisual Composer
Visual Composer users are required to execute WPBMap::addAllMappedShortcodes() prior to calling the_content() in an Ajax requests – see the example below:
<?php
WPBMap::addAllMappedShortcodes();
the_content();
?>
PHPYes, but please be aware that if you set a single_post_taxonomy value in the shortcode and the current post has multiple terms assigned, Ajax Load More will look for posts where ANY of the assigned terms are present.
Note: Setting a primary category or term does not affect a post query – this is out of the box WP functionality that cannot be adjusted.
This issue can arise if you have floated elements in your repeater template.
For example, your main post container has a float: left;
CSS property assigned – this may cause the positioning of the load more button to become unreliable and cause posts and URLs to update prematurely.
A solution to this problem is to ensure your floated elements are always cleared by assigning the following CSS to the .alm-single-post
container.
.alm-single-post{ overflow: hidden; }
This happens in some themes and frameworks because of the way the templates have been structured. To fix this issue add the following code snippet to the start of the Repeater Template.
<article>
<?php
global $more;
$more = true;
// The rest of your template goes here!
// the_content(); etc.
?>
</article>
PHP