I am currently building a WordPress site. Within this site are author pages that show first ten posts, with a load more button to get the next ten via an Ajax call. For one author in particular, it is duplicating the last post on the list and the only reason I can see is that they have a draft post within the first ten that is being counted by offset. This works flawlessly everywhere else so I can't figure out what's wrong.
Functions.php
if (!function_exists('bookreview_moreajax')) {
function bookreview_moreajax(){
$ppp = (isset($_POST['ppp'])) ? $_POST['ppp'] : 3;
$cat = (isset($_POST['cat'])) ? $_POST['cat'] : 0;
$auth = (isset($_POST['auth'])) ? $_POST['auth'] : 0;
$offset = (isset($_POST['offset'])) ? $_POST['offset'] : 0;
$args = array(
'post_type' => 'post',
'posts_per_page' => $ppp,
'cat' => $cat,
'offset' => $offset,
'author_name' => $auth,
);
$loop = new WP_Query($args);
$out = '';
if ($loop -> have_posts()) :
while ($loop -> have_posts()) :
$loop -> the_post();
$out = get_template_part( 'template-parts/content', 'list' );
endwhile;
endif;
wp_reset_postdata();
wp_die($out);
}
}
Ajax.js
(function ($) {
"use strict";
/*jslint browser: true*/
/*global $,console,ajaxpagination*/
//AJAX MORE POSTS
//global variables
var $content = $('.ajax_posts'),
$pageloader = $('#more_posts'),
$catloader = $('.categories_EBR .radio-buttons li.cat-item'),
offset = 0,
auth = '',
cat = '',
loading = false;
//show load more button and hide pagination
if (($pageloader).length) {
$('.navigation').css('display', 'none');
$pageloader.css('display', 'block');
}
function get_ajax_posts(ppp, method, $loader) {
loading = true;
//set offset depending on method
if (method === 'append') {
offset = $('#main').find('.type-post').length;
} else {
$content.css({ opacity: 0.5 });
offset = 0;
}
//start ajax call
$.ajax({
type: 'POST',
dataType: 'html',
url: ajaxpagination.ajaxurl,
data: {
'cat': cat,
'ppp': ppp,
'offset': offset,
'auth': auth,
'action': 'bookreview_moreajax'
},
beforeSend : function () {
$('body').addClass('ajax-loading');
},
success: function (data) {
loading = false;
var $data = $(data);
if ($data.length) {
var $newElements = $data.css({ opacity: 0 });
//update or replace depending on method
if (method === 'append') {
$content.append($newElements);
} else if (method === 'replace') {
$content.html($data);
} else {
console.log('Unknown method: ' + method);
return false;
}
//update Load More button with correct category
$pageloader.data('category', cat);
$newElements.animate({ opacity: 1 }, 200);
$pageloader.css({ opacity: 1 }).html(ajaxpagination.loadmore);
} else {
$pageloader.css({ opacity: 1 }).addClass('no_more_posts').html(ajaxpagination.noposts);
}
$content.css({ opacity: 1});
$loader.removeClass('ajax-loader');
$('body').removeClass('ajax-loading');
},
error : function (jqXHR, textStatus, errorThrown) {
loading = false;
$pageloader.html($.parseJSON(jqXHR.responseText) + ' :: ' + textStatus + ' :: ' + errorThrown);
console.log(jqXHR);
}
});
offset += ppp;
return false;
}
function get_more(event) {
if (loading || $pageloader.hasClass('no_more_posts')) {
console.log("Stahp!");
return;
}
var ppp = 6,
method = 'append',
$loader = $(event.currentTarget);
if ($pageloader.attr('data-category')) {
cat = $pageloader.data('category');
} else if ($pageloader.attr('data-author')) {
auth = $pageloader.data('author');
}
$loader.addClass('ajax-loader');
get_ajax_posts(ppp, method, $loader);
}
function get_cat(event) {
event.preventDefault();
if (loading) {
console.log("Stahp!");
return;
}
var $loader = $(event.currentTarget),
$cats = $('.cat-item'),
ppp = 10,
method = 'replace';
if (!($loader.hasClass('current-cat'))) {
$cats.removeClass('current-cat');
cat = $loader.attr('class').match(/\d+/)[0];
$loader.addClass('current-cat');
} else {
cat = $('body').attr('class').match(/\d+/)[0];
$cats.removeClass('current-cat');
}
$pageloader.removeClass('no_more_posts');
get_ajax_posts(ppp, method, $loader);
}
//triggers
$pageloader.on('click', get_more);
$catloader.on('click', get_cat);
}(jQuery));
It just seems that when it goes to get the next ten posts, the offset number (10) seems to count the draft post and is therefore one behind what it should be, resulting in a duplicate post. Am I missing something obvious?
EDIT - When i add post_status => 'published' to the query args it skips 10 posts (same value as offset). When I force the offset to 0 it just repeats the first 10. If I remove the post status it continues to count draft posts.
EDIT2 - It turns out that it's because I have a load of private posts. By adding this to my Functions.php the problem is fixed:
// check if user is editor or higher to allow viewing private posts
if( current_user_can('editor') || current_user_can('administrator') ) {
$post_status = array ('publish', 'private');
} else {
$post_status = array ('publish');
}
$args = array(
'post_status' => $post_status,
'posts_per_page' => $ppp,
'cat' => $cat,
'offset' => $offset,
'author_name' => $auth,
);
Still wondering why this doesn't happen automatically (as it does by default), seems a bit messy to have to do it this way. Any advice on how to do this more cleanly?