I've had a look through the old questions and tried many of the different methods that there seems to be to do this. The closest I've got to working is this one here: How to implement pagination on a custom WP_Query Ajax
I've tried everything and it just doesn't work. Absolutely nothing changes on the page. If you inspect the Load More Button and click it, the jQuery is making the Load More Button action as it changes from <a id="more_posts">Load More</a> to <a id="more_posts" disables="disabled">Load More</a> which even that doesn6't seem right to me anyway. It's not adding the posts, I think I'm missing something simple but for the life of me I can't work it out.
The code in my template file is:
<div id="ajax-posts" class="row">
<?php
$postsPerPage = 3;
$args = [
'post_type' => 'post',
'posts_per_page' => $postsPerPage,
'cat' => 1
];
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post(); ?>
<div class="small-12 large-4 columns">
<h1><?php the_title(); ?></h1>
<p><?php the_content(); ?></p>
</div>
<?php
endwhile;
echo '<a id="more_posts">Load More</a>';
wp_reset_postdata();
?>
</div>
The code in my functions file is:
function more_post_ajax(){
$offset = $_POST["offset"];
$ppp = $_POST["ppp"];
header("Content-Type: text/html");
$args = [
'suppress_filters' => true,
'post_type' => 'post',
'posts_per_page' => $ppp,
'cat' => 1,
'offset' => $offset,
];
$loop = new WP_Query($args);
while ($loop->have_posts()) { $loop->the_post();
the_content();
}
exit;
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
And my jQuery in the footer is:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready( function($) {
var ajaxUrl = "<?php echo admin_url('admin-ajax.php')?>";
// What page we are on.
var page = 5;
// Post per page
var ppp = 3;
$("#more_posts").on("click", function() {
// When btn is pressed.
$("#more_posts").attr("disabled",true);
// Disable the button, temp.
$.post(ajaxUrl, {
action: "more_post_ajax",
offset: (page * ppp) + 1,
ppp: ppp
})
.success(function(posts) {
page++;
$("#ajax-posts").append(posts);
// CHANGE THIS!
$("#more_posts").attr("disabled", false);
});
});
});
</script>
Can anybody see something I'm missing or able to help?
UPDATE 24.04.2016.
I've created tutorial on my page https://madebydenis.com/ajax-load-posts-on-wordpress/ about implementing this on Twenty Sixteen theme, so feel free to check it out :)
EDIT
I've tested this on Twenty Fifteen and it's working, so it should be working for you.
In index.php (assuming that you want to show the posts on the main page, but this should work even if you put it in a page template) I put:
<div id="ajax-posts" class="row">
<?php
$postsPerPage = 3;
$args = array(
'post_type' => 'post',
'posts_per_page' => $postsPerPage,
'cat' => 8
);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
?>
<div class="small-12 large-4 columns">
<h1><?php the_title(); ?></h1>
<p><?php the_content(); ?></p>
</div>
<?php
endwhile;
wp_reset_postdata();
?>
</div>
<div id="more_posts">Load More</div>
This will output 3 posts from category 8 (I had posts in that category, so I used it, you can use whatever you want to). You can even query the category you're in with
$cat_id = get_query_var('cat');
This will give you the category id to use in your query. You could put this in your loader (load more div), and pull with jQuery like
<div id="more_posts" data-category="<?php echo $cat_id; ?>">Load More</div>
And pull the category with
var cat = $('#more_posts').data('category');
But for now, you can leave this out.
Next in functions.php I added
wp_localize_script( 'twentyfifteen-script', 'ajax_posts', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'noposts' => __('No older posts found', 'twentyfifteen'),
));
Right after the existing wp_localize_script. This will load WordPress own admin-ajax.php so that we can use it when we call it in our ajax call.
At the end of the functions.php file I added the function that will load your posts:
function more_post_ajax(){
$ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 3;
$page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
header("Content-Type: text/html");
$args = array(
'suppress_filters' => true,
'post_type' => 'post',
'posts_per_page' => $ppp,
'cat' => 8,
'paged' => $page,
);
$loop = new WP_Query($args);
$out = '';
if ($loop -> have_posts()) : while ($loop -> have_posts()) : $loop -> the_post();
$out .= '<div class="small-12 large-4 columns">
<h1>'.get_the_title().'</h1>
<p>'.get_the_content().'</p>
</div>';
endwhile;
endif;
wp_reset_postdata();
die($out);
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
Here I've added paged key in the array, so that the loop can keep track on what page you are when you load your posts.
If you've added your category in the loader, you'd add:
$cat = (isset($_POST['cat'])) ? $_POST['cat'] : '';
And instead of 8, you'd put $cat. This will be in the $_POST array, and you'll be able to use it in ajax.
Last part is the ajax itself. In functions.js I put inside the $(document).ready(); enviroment
var ppp = 3; // Post per page
var cat = 8;
var pageNumber = 1;
function load_posts(){
pageNumber++;
var str = '&cat=' + cat + '&pageNumber=' + pageNumber + '&ppp=' + ppp + '&action=more_post_ajax';
$.ajax({
type: "POST",
dataType: "html",
url: ajax_posts.ajaxurl,
data: str,
success: function(data){
var $data = $(data);
if($data.length){
$("#ajax-posts").append($data);
$("#more_posts").attr("disabled",false);
} else{
$("#more_posts").attr("disabled",true);
}
},
error : function(jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
return false;
}
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
load_posts();
});
Saved it, tested it, and it works :)
Images as proof (don't mind the shoddy styling, it was done quickly). Also post content is gibberish xD
UPDATE
For 'infinite load' instead on click event on the button (just make it invisible, with visibility: hidden;) you can try with
$(window).on('scroll', function () {
if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
load_posts();
}
});
This should run the load_posts() function when you're 100px from the bottom of the page. In the case of the tutorial on my site you can add a check to see if the posts are loading (to prevent firing of the ajax twice), and you can fire it when the scroll reaches the top of the footer
$(window).on('scroll', function(){
if($('body').scrollTop()+$(window).height() > $('footer').offset().top){
if(!($loader.hasClass('post_loading_loader') || $loader.hasClass('post_no_more_posts'))){
load_posts();
}
}
});
Now the only drawback in these cases is that you could never scroll to the value of $(document).height() - 100 or $('footer').offset().top for some reason. If that should happen, just increase the number where the scroll goes to.
You can easily check it by putting console.logs in your code and see in the inspector what they throw out
$(window).on('scroll', function () {
console.log($(window).scrollTop() + $(window).height());
console.log($(document).height() - 100);
if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
load_posts();
}
});
And just adjust accordingly ;)
Hope this helps :) If you have any questions just ask.
If I'm not using any category then how can I use this code? Actually, I want to use this code for custom post type.
Related
I have custom post types with JS filtering (based on category). There are simple html boxes + php code with ACF fields what display after select category.
Problem is it take 1 second or more to load all this html boxes so its not so smooth.
This is my JS (file filters.js):
(function($){
$(document).ready(function(){
$(document).on('click', '.js-filter-item > a', function(e){
e.preventDefault();
var category = $(this).data('category');
$.ajax({
url:wp_ajax.ajax_url,
data: { action: 'filter', category: category },
type: 'post',
success: function(result) {
$('.js-filter').html(result);
},
error: function(result) {
console.warn(result);
}
});
});
});
})(jQuery);
This is html of box what is loaded (file content_pozice_box.php)
<a href="<?php echo get_permalink();?>"><div class="vypis_pozice">
<div class="projekt-wrapper">
<?php
$projekt = get_field('projekt');
if( get_field('projekt') == 'XXX' ) {
?>
<div class="logo-wrapper">
<img src="https://YYY.png" class="logo-wrapper-img">
</div><?php
}
if( get_field('projekt') == 'YYY' ) {
?>
<div class="logo-wrapper">
<img src="https://XXX.png" class="logo-wrapper-img">
</div>
<?php
}
?>
<div class="field_projekt"><h3><?php the_field('projekt');?></h3><div class="field_AAA">AAA:
<?php if ( get_field( 'AAA' ) ): ?>
<?php the_field('AAA');?>
<?php else: // field_name returned false ?>
dohodou
<?php endif; // end of if field_name logic ?>
</div></div>
</div>
<?php the_title('<h3>', '</h3>'); ?>
<div class="location-wrapper">
<div class="BBB"><img src="https://BBB.png"><?php the_field('BBB');?></div>
<div class="CCC"><img src="https://CCC.png"><?php the_field('CCC');?></div>
</div>
<div class="DDD"><?php $cat = get_the_category(); echo $cat[0]->cat_name; ?></div><div class="job-button">Otevřít</div>
</div></a>
PHP (loading JS, Ajax, function)
function load_scripts() {
wp_enqueue_script('ajax', get_stylesheet_directory_uri() . '/' . 'template-parts/' .'filters.js', array('jquery'), NULL, true);
wp_localize_script('ajax' , 'wp_ajax',
array('ajax_url' => admin_url('admin-ajax.php'))
);
}
add_action( 'wp_enqueue_scripts', 'load_scripts');
add_action( 'wp_ajax_nopriv_filter', 'filter_ajax' );
add_action( 'wp_ajax_filter', 'filter_ajax' );
function filter_ajax() {
$category = $_POST['category'];
$args = array(
'post_type' => 'pozice',
'posts_per_page' => -1
);
if(isset($category)) {
$args['category__in'] = array($category);
}
$query = new WP_Query($args);
if($query->have_posts()) :
while($query->have_posts()) : $query->the_post();
include("content_pozice_box.php");
endwhile;
endif;
wp_reset_postdata();
die();
}
This won't solve all your problems but the first thing you should do is reduce your database calls. get_field('projekt') is called 4 times, which runs for every iteration of your loop. Oddly, you've already set it to a variable:
$projekt = get_field('projekt');
But you're not using the variable anywhere. So try replacing that first, so that it only runs once per iteration:
if ( $projekt ) {...}
While you're at it you should always escape output for security's sake. I.E. Instead of <h3><?php the_field('projekt');?></h3> replace with <h3><?php echo esc_html( $projekt ); ?></h3>.
To find other sources of inefficiencies you might try the Query Monitor plugin, as well as your browser's dev tools. I'm not sure about your JS. It looks fine to me but perhaps someone else here will notice something.
I've been trying (and failing annoyingly) to get an Ajax post loader to work.
This is the jQuery i'm using (its from this previous StackOverflow post: "Load More Posts" with Ajax in wordpress ), but its just not working.. I'm just trying to get an isotope list to ajax load more but everything i'm trying is failing.
jQuery(document).ready(function($){
$('.pagination a').click(function(e) {
e.preventDefault();
$('.filtered-posts').append("<div class=\"loader\"> </div>");
var link = jQuery(this).attr('href');
var $content = '.filtered-posts';
var $nav_wrap = '.pagination';
var $anchor = '.pagination a';
var $next_href = $($anchor).attr('href'); // Get URL for the next set of posts
$.get(''+link+' .item', function(data){
var $timestamp = new Date().getTime();
var $new_content = $($content, data).wrapInner('').html(); // Grab just the content
$('.filtered-posts .loader').remove();
$next_href = $($anchor, data).attr('href'); // Get the new href
$($nav_wrap).before($new_content); // Append the new content
$('#rtz-' + $timestamp).hide().fadeIn('slow'); // Animate load
$('.pagination a').attr('href', $next_href); // Change the next URL
$('.pagination:last').remove(); // Remove the original navigation
});
});});
This is what I'm using for my js but its just not loading anything when I click on the standard previous_posts_link/next_posts_link.
I've put a div container around them to force the .pagination above.. It briefly worked but was only calling the same 9 posts once and then didn't work.
Any help would be great. Or if someone has a different Ajax Pagination guide that they know works ..
Thanks in advance :)
/* We will edit our javascript snippet with a variable to keep track of the current page, and we add the $ajax call to our ajax function that we will write in the next chapter. */
let currentPage = 1;
jQuery('#load-more').on('click', function() {
currentPage++; // Do currentPage + 1, because we want to load the next page
jQuery.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php'); ?>',
dataType: 'html',
data: {
action: 'weichie_load_more',
paged: currentPage,
},
success: function (res) {
jQuery('.publication-list').append(res);
}
});
});
/* The WordPress query to load posts from a (custom) post type */
<?php
$publications = new WP_Query([
'post_type' => 'publications',
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
'paged' => 1,
]);
?>
<?php if($publications->have_posts()): ?>
<ul class="publication-list">
<?php
while ($publications->have_posts()): $publications->the_post();
get_template_part('parts/card', 'publication');
endwhile;
?>
</ul>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
<div class="btn__wrapper">
Load more
</div>
functions.php:
function weichie_load_more() {
$ajaxposts = new WP_Query([
'post_type' => 'publications',
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
'paged' => $_POST['paged'],
]);
$response = '';
if($ajaxposts->have_posts()) {
while($ajaxposts->have_posts()) : $ajaxposts->the_post();
$response .= get_template_part('parts/card', 'publication');
endwhile;
} else {
$response = '';
}
echo $response;
exit;
}
add_action('wp_ajax_weichie_load_more', 'weichie_load_more');
add_action('wp_ajax_nopriv_weichie_load_more', 'weichie_load_more');
I cant get this to work. I am trying to create a custom post type grid with ajax load more button to show 6 mosts per page in the grid. I can get the posts to show but the Load More button just scrolls to the top of the page like a normal anchor link.
My theme code:
<div class="tabgrid">
<?php
$postsPerPage = 6;
$args = array(
'post_type' => 'dslc_projects',
'posts_per_page' => $postsPerPage,
'offset' => $offset
);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
?><div class="project-grid-item">
<a href="<?php the_permalink() ?>">
<h3><?php the_title() ?></h3>
<p>View project...</p> </a>
</div><?php
endwhile; ?>
<?php echo '<div id="more_posts">Load More</div>';
wp_reset_postdata();
?>
</div>
</div>
My PHP:
function more_post_ajax(){
$offset = $_POST["offset"];
$ppp = $_POST["ppp"];
header("Content-Type: text/html");
$args = array(
'post_type' => 'post',
'posts_per_page' => $ppp,
'offset' => $offset
);
$loop = new WP_Query($args);
while ($loop->have_posts()) { $loop->the_post();
the_content();
}
exit;
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
My JS:
var ajaxUrl = "<?php echo admin_url('admin-ajax.php')?>";
var page = 1; // What page we are on.
var ppp = 6; // Post per page
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
$.post(ajaxUrl, {
action:"more_post_ajax",
offset: (page * ppp) + 1,
ppp: ppp
}).success(function(posts){
page++;
$(".tabgrid").append(posts); // CHANGE THIS!
$("#more_posts").attr("disabled",false);
});
});
can anyone see what could be wrong here?
Your anchor is just a normal anchor and href="#" means scroll to top. Your JS code is trying to add a handler to and element with the id "#more_posts" but your anchor doesn't have an id.
Try replacing your anchor with <div id="more_posts">Load More</div>
So essentially I'm able to get WP and AJAX to load a page whenever I've got a 'click' event in JQuery. With the click event it works properly, however, when switching it all to function on scroll, instead of properly reloading the following post or posts (as it does when you click) it instead reloads the entire page of the site within the designated div.
Here's my code:
Ajax.php
add_action('wp_ajax_nopriv_art_load_single','art_load_single');
add_action('wp_ajax_art_load_single','art_load_single');
function art_load_single(){
$paged = $_POST["page"]+1;
$query = new WP_Query(array(
'post_type' => 'post',
'post_status' => 'publish',
'paged' => $paged,
'posts_per_page' => 1
));
?>
<?php if($query->have_posts()):
while($query->have_posts()): $query->the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<div class="entry-title">
<?php the_title( '<h1>', '</h1>' ); ?>
<h2 class="sub-headline">
<?php if ( ! has_excerpt() ) {
echo '';
} else {
the_excerpt();
} ?>
</h2>
</div>
<?php if ( has_post_thumbnail()) : ?>
<div class="article-featured-image">
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
</header><!-- .entry-header -->
<div class="entry-content">
<?php the_content(); ?>
<?php
wp_link_pages( array(
'before' => '<div class="page-links">' . __( 'Pages:', 'some_theme' ),
'after' => '</div>',
) );
?>
</div><!-- .entry-content -->
</article><!-- #post-## -->
<?php endwhile;
endif;
wp_reset_postdata(); ?>
<?php die();
}
Load-more.js
var postContainer = document.getElementById('primary');
var request_in_progress = false;
$(window).scroll(function(){
infiniteScroll();
});
function infiniteScroll(){
var content_height = postContainer.offsetHeight;
var current_y = window.innerHeight + window.pageYOffset;
if(current_y >= content_height)
showSinglePost();
}
}
//$(document).on('click','.load-single-article', function(){
function showSinglePost(){
if(request_in_progress) { return; }
request_in_progress = true;
var that = $(this);
var page = that.data('page');
var newPage = page+1;
var ajaxurl = that.data('url');
that.find('.text').html('LOADING...');
$.ajax({
url : ajaxurl,
type : 'post',
data : {
page : page,
action : 'art_load_single',
dataType: 'post'
},
error : function( response ){
console.log(response);
},
success : function( response ) {
setTimeout(function(){
that.data('page', newPage);
$('#primary').append( response );
that.find('.text').html('VIEW MORE');
request_in_progress = false;
}, 500);
}
});
}
Leaving in the 'click' event just in case. Finally my button for clicking is below:
<a class="view-btn load-single-article" data-page="1" data-url="<?php echo admin_url('admin-ajax.php'); ?>"><span class="text">VIEW MORE</span></a>
Being slightly new to AJAX I believe it could just be the URL reacts differently when called on click vs when loading on scroll, or maybe the click is just working as a fluke. Any help is appreciated!
This is a stripped back version of what you want, so you should be able to just plug in your own article loading etc.. It starts off with a bunch of articles already loaded and when you scroll it checks to see where one the page you are. If you're at the bottom of the page then it loads a new article and appends it.
var articleCount = 0;
var $window = $(window);
var $body = $("body");
$window.on("scroll", function() {
// check to see if we're near the bottom of the page
if ($window.scrollTop() > $body.height() - $window.innerHeight()) {
// we are at the bottom, so load a new article
loadNextArticle();
}
});
// make this function actually load an article and append it to the page
function loadNextArticle() {
articleCount++;
$body.append("<div class=\"single-article\">I am article number " + articleCount + "</div>");
}
// create some articles when the page loads...
for (var i = 0; i < 6; i++) {
loadNextArticle();
}
.single-article {
background-color: rgb(230, 230, 240);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 10px;
height: 200px;
margin: 10px;
padding: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Obviously you'll need to amend this to suit your specific requirements, but I've tried to make it as generic as possible. Realistically you should just be able to copy/paste the Javascript into your site and swap out the part that loads and appends a new article.
I have custom post types displaying on a static front page, initially showing 8 posts, where I have now created a load more button using an example of jQuery and AJAX that I found online that will show 4 more posts when the button is clicked. I am wondering how I can add 4 to the offset each time so it keeps moving through the next posts. As it is now every time I click the load more button it shows the same 4 over again. My code in my front-page.php:
<script>
var now=2; // when click start in page 2
jQuery(document).on('click', '#load_more_btn', function () {
jQuery.ajax({
type: "POST",
url: "<?php echo get_site_url(); ?>/wp-admin/admin-ajax.php",
data: {
action: 'my_load_more_function', // the name of the function in functions.php
paged: now, // set the page to get the ajax request
posts_per_page: 4, //number of post to get (use 1 for testing)
},
success: function (data) {
if(data!=0){
jQuery("#ajax").append(data); // put the content into ajax container
now=now+1; // add 1 to next page
}else{
jQuery("#load_more_btn").html("<h4>No more
results</h4>");
}
},
error: function (errorThrown) {
alert(errorThrown); // only for debuggin
}
});
});
and the code in my functions.php file:
add_action('wp_ajax_my_load_more_function', 'my_load_more_function');
add_action('wp_ajax_nopriv_my_load_more_function',
'my_load_more_function');
function my_load_more_function() {
$offset = 8;
$page = (get_query_var('page')) ? get_query_var('page') : 1;
$query = new WP_Query( [
'posts_per_page' => $_POST["posts_per_page"],
'order'=>'ASC',
'offset'=> $offset,
'post_type' => 'videos',
'page' => get_query_var('page', $_POST["paged"])
] );
if ($query->have_posts()) {
$offset = (($page - 1) * 8) - $offset;
$query->set( 'offset', $offset );
while ($query->have_posts()) {
$query->the_post();
$img1 = get_field('video_thumbnail'); ?>
<div class="col-6 col-sm-3 box no-gutters" style="background-
image: url('<?php echo $img1['url']; ?>')"><a href="<?php
the_field('video_link'); ?>" data-lity><div class="overlay"><span
class="title"><?php the_field('name'); ?></span></div></a></div>
<?php
}
wp_reset_query();
}else{
return 0;
}
exit;
}
I'm wondering how I can get offset to be +4 each time the query is run after the initial time where it is set at 8. I'm fairly new to thsi type of thing and can not seem to get it working properly.