AJAX Interfering with if statement in while loop? - javascript

I am trying to load my sidebars in my while loop by using if statements that call them after a certain number of posts. It's important to note that I am using AJAX code (provided below) to load in posts on scroll and I believe it may be causing the issue.
Though they are sidebars, they are not physically a sidebar but rather content loaded between posts.
I've tried for a week to locate the problem but I cannot seem to get the sidebars to load with AJAX as a if statement in the while loop.
Important to note: The sidebar will load after the number of posts if it's not loaded through AJAX. So if it's in the initial load, the sidebars load. But when you continue to scroll to say the third or fourth bar it will not load and the AJAX will only load the (parts/content).
I need to either be able to resolve the if statement so it works within the while loop that loads through AJAX or I'm open to an alternate solution as long as it doesn't remove the AJAX.
A lot of work has been put into making this loop work and help is greatly appreciated!
front-page.php
<?php
$current_page = max( 1, get_query_var( 'paged' ) );
$the_query = new WP_Query( array(
'cat' => '-21',
'post_type' => 'post',
'posts_per_page' => 5,
'paged' => $current_page,
'tax_query' => array(
array(
'taxonomy' => 'topics',
'operator' => 'NOT EXISTS',
'field' => 'term_id',
'terms' => $term_id
)
)
) );
wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array(
'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ),
'posts' => json_encode( $the_query->query_vars ),
'current_page' => $current_page,
'max_page' => $the_query->max_num_pages
) );
?>
<div id="main" class="container-fluid">
<?php if ($the_query->have_posts()) : ?>
<?php $count = 0; ?>
<?php while ($the_query->have_posts()) : $the_query->the_post(); get_template_part( 'parts/content', get_post_format() ); ?> <!-- This parts/content loads -->
<?php $count++; ?>
<!-- the dynamic_sidebar does not load -->
<?php if ($count == 2 && is_active_sidebar('sidebar1') ) : ?>
<div class="side-container first-side">
<?php dynamic_sidebar('sidebar1'); ?>
</div>
<?php endif; ?>
<?php if ($count == 10 && is_active_sidebar('sidebar2') ) : ?>
<div class="side-container first-side">
<?php dynamic_sidebar('sidebar2'); ?>
</div>
<?php endif; ?>
<?php if ($count == 20 && is_active_sidebar('sidebar3') ) : ?>
<div class="side-container third-side">
<?php dynamic_sidebar('sidebar3'); ?>
</div>
<?php endif; ?>
<?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
<?php get_footer(); ?>
</div><!-- END CONTAINER -->
parts/content -- this loads as expected including code if it's helpful
<div class="row post"> <!-- Post is mentioned in the below JS to load -->
<div class="col-sm-5">
<h2>Text</h2>
</div>
<div class="col-sm-7">
<h3>text</h3>
</div>
</div><!-- END ROW-->
sidebar code - works when initially loaded but doesn't when AJAX calls on this code such as the last two sidebars in front-page.php
<?php
$term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); ?>
<?php while( $flexible_posts->have_posts() ) : $flexible_posts->the_post(); global $post; ?>
<div class="sidebar-area">
//sidebar code here
}
endwhile;
?>
myloadmore.js - AJAX Call
jQuery(function($){
var canBeLoaded = true,
bottomOffset = 2000;
$(window).scroll(function(){
if ( misha_loadmore_params.current_page >= misha_loadmore_params.max_page ) {
return;
}
var data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts,
'page' : misha_loadmore_params.current_page
};
if( $(document).scrollTop() > ( $(document).height() - bottomOffset ) && canBeLoaded == true ){
$.ajax({
url : misha_loadmore_params.ajaxurl,
data: data,
type: 'POST',
beforeSend: function( xhr ){
// AJAX call is in process, we shouldn't run it again until complete
canBeLoaded = false;
},
success:function(data){
if( data ) {
$('#main').find('div.post:last-of-type').after( data ); // where to insert posts
canBeLoaded = true; // the ajax is completed, now we can run it again
misha_loadmore_params.current_page++;
bottomOffset = ( $( '#main > div.post:last' ).offset() || {} ).top
}
}
});
}
});
});
functions.php - Added for further context
function misha_my_load_more_scripts() {
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/js/myloadmore.js',
array( 'jquery' ), '', true );
wp_enqueue_script( 'my_loadmore' );
}
add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' );
function misha_loadmore_ajax_handler() {
$args = json_decode( wp_unslash( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // load the next page
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) :
while ( $the_query->have_posts() ) : $the_query->the_post();
get_template_part( 'parts/content', get_post_format() );
endwhile;
endif;
wp_die();
}
add_action( 'wp_ajax_loadmore', 'misha_loadmore_ajax_handler' ); // Authenticated users
add_action( 'wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler' ); // Non-authenticated users

The trick here was to add the if statements inside of the AJAX handlers as well. Perhaps someone with AJAX experience can add to this one day to explain why it works, but all I know is that it does. All the code from my question is the same below is the difference from the functions.php ajax handler function.
function misha_loadmore_ajax_handler() {
$args = json_decode( wp_unslash( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // load the next page
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) :
while ( $the_query->have_posts() ) : $the_query->the_post();
get_template_part( 'parts/content', get_post_format() );
<?php if ($count == 2 && is_active_sidebar('sidebar1') ) : ?>
<div class="side-container first-side">
<?php dynamic_sidebar('sidebar1'); ?>
</div>
<?php endif; ?>
<?php if ($count == 10 && is_active_sidebar('sidebar2') ) : ?>
<div class="side-container first-side">
<?php dynamic_sidebar('sidebar2'); ?>
</div>
<?php endif; ?>
<?php if ($count == 20 && is_active_sidebar('sidebar3') ) : ?>
<div class="side-container third-side">
<?php dynamic_sidebar('sidebar3'); ?>
</div>
<?php endif;
endwhile;
endif;
wp_die();
}

Related

Speed up admin-ajax.php request in CPT filters

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.

Troubleshooting Ajax Post Filter in WordPress - Not responding to WP_Query

I've created an Ajax post filter for a blog. When you click a category to filter the posts below, what happens is odd. The markup of the current page is injected rather than the results of my WP_Query arguments. So you end up with the page nested within itself.
Here's my post filter bar with the initial query populating the response div:
Here's the form:
<form action="<?php echo admin_url('admin-ajax.php'); ?>" method="POST" id="filter">
<label><input type="radio" name="category" value="" checked="checked"><div>All</div></label>
<!-- Loop Selected Categories -->
<label><input type="radio" name="category" value="Category_ID"><div>Category Name</div></label>
<!-- End Loop Selected Categories -->
<input type="submit" value="Submit">
<input type="hidden" name="action" value="myfilter">
</form>
Below is my JavaScript:
jQuery(document).ready(function($) {
$('#filter').submit(function(){
var filter = $('#filter');
$.ajax({
url:ajax_object.ajaxurl,
data:filter.serialize(), // form data
type:filter.attr('method'), // POST
success:function(data){
$('#response').html(data); // insert data
}
});
console.log('form submitted');
return false;
});
$('#filter input[type=radio]').on('change', function() {
$("#filter").submit();
});
});
Below the filter form there's a response div that contains the initial/default query results:
<div class="post-grid" id="response">
<?php
$args = array(
'posts_per_page' => 5,
'post_status' => array('publish')
);
$query = new WP_Query( $args );
if( $query->have_posts() ) :
while( $query->have_posts() ): $query->the_post();
return get_template_part( 'template-parts/content-card' );
endwhile;
wp_reset_postdata();
else :
echo 'No posts found';
endif;
?>
</div>
I have the following code to query the selected category in my functions.php:
// In my enqueued scripts
wp_enqueue_script( 'post_filter_js', get_template_directory_uri() . '/dist/js/post-filter.min.js', array('jquery'), '', true );
wp_localize_script( 'post_filter_js', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
// Function to query the selected category
add_action('wp_ajax_myfilter', 'filter_post_by_cat');
add_action('wp_ajax_nopriv_myfilter', 'filter_post_by_cat');
function filter_post_by_cat(){
// for taxonomies / categories
if( isset( $_POST['category'] ) ):
$args = array(
'category__in' => $_POST['category'],
'posts_per_page' => 5,
'post_status' => array('publish')
);
endif;
$query = new WP_Query( $args );
if( $query->have_posts() ) :
while( $query->have_posts() ): $query->the_post();
echo get_template_part( 'template-parts/content-card' );
endwhile;
wp_reset_postdata();
else :
echo 'No posts found';
endif;
die();
}

when button clicked send post-id inside variable

I have a query that displays events and there is a buy now button.
How do I make that when I press this button I send in a php session the post-id of the post that this button is inside of.
With what I have done so far the problem is that when I press the button I get the variable of the post-id of the last post in the loop instead of the post-id of the button I am pressing.
This is my code:
function calendario_posts( ) {
ob_start();
// WP_Query arguments
$paged = (get_query_var(‘paged’)) ? get_query_var(‘paged’) : 1;
$args = array (
'category_name' => 'calendario',
'posts_per_page' => '6',
'paged' => $paged
);
// The Query
$featured_post_query = new WP_Query( $args );
// The Loop
if ( $featured_post_query->have_posts() ) {
while ( $featured_post_query->have_posts() ) {
$featured_post_query->the_post();
?>
<div class="teatro-all">
<?php the_post_thumbnail(gallery); ?>
<h2 class="teatro-group teatro-title"><?php the_title(); ?></h2>
<h5 class="teatro-group teatro-fecha"> <?php the_field('fecha'); ?></h5>
<h5 class="teatro-group teatro-precio" >Precio desde: <?php the_field('precio'); ?></h5>
<?php $eventTitle = get_the_title(); ?>
<center><a class="teatro-buy teatro-button" href="http://localhost/newiga/tickets/">COMPRAR</a><br>
<center><a class="teatro-read-more teatro-button" href="<?php the_permalink(); ?>">LEER MAS</a></center>
<script> var buybutton = document.getElementById("teatro-buy");
buybutton.onclick = function(){
<?php $_SESSION['eventId'] = get_the_ID();?>
}
</script>
<?php
}
} else {
// no posts found
}
// Restore original Post Data
wp_reset_postdata();
}
function calendario_shortcode() {
$output = calendario_posts();
$output = ob_get_clean();
return $output;
}
add_shortcode( 'calendario', 'calendario_shortcode' );

AJAX handler throws 400 (Bad request) - why?

I am trying to apply a "Load more posts" function to a post loop, but I am dealing with a 400 Bad request, when admin-ajax.php is referred to.
The reference I used is this - https://rudrastyh.com/wordpress/load-more-posts-ajax.html
Following function (in functions.php) is passing query parameters to javascript:
function wordpress_my_load_more_scripts()
{
global $wp_query;
wp_enqueue_script('jquery');
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/myloadmore.js', array('jquery') );
wp_localize_script( 'my_loadmore', 'wordpress_loadmore_params', array(
'ajaxurl' => admin_url() . 'admin-ajax.php',
'posts' => json_encode( $wp_query->query_vars ),
'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $wp_query->max_num_pages
) );
wp_enqueue_script( 'my_loadmore' );
}
add_action( 'wp_enqueue_scripts', 'wordpress_my_load_more_scripts' );
Parameters are passed to following jQuery script named "myloadmore.js":
jQuery(function($){
$('.wordpress_loadmore').click(function()
{
var button = $(this),
data = {
'action': 'loadmore',
'query': wordpress_loadmore_params.posts,
'page' : wordpress_loadmore_params.current_page
};
console.log(wordpress_loadmore_params.ajaxurl);
$.ajax({
url : wordpress_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr )
{
button.text('Loading...');
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().before(data);
wordpress_loadmore_params.current_page++;
if ( wordpress_loadmore_params.current_page == wordpress_loadmore_params.max_page )
button.remove(); // if last page, remove the button
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
});
Following function inside functions.php is expected to provide three more posts inside while loop:
function wordpress_loadmore_ajax_handler()
{
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
query_posts( $args );
if(have_posts() ) :
echo "We have post(s)!";
while( have_posts() ): the_post();
echo "A post!";
endwhile;
endif;
die;
}
add_action('wp_ajax_loadmore', 'wordpress_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmore', 'wordpress_loadmore_ajax_handler');
The post loop is this:
<ul class="products columns-3">
<?php
$query_params = array(
'post_type' => 'post',
'posts_per_page' => 3
);
$wp_query = new WP_Query( $query_params);
if( $wp_query->have_posts() ) :
while ($wp_query->have_posts()) : $wp_query->the_post(); ?>
<li class="product post-item">
<span class="post-image">
<a href="<?php the_permalink(); ?>">
<?php
if ( has_post_thumbnail())
{
the_post_thumbnail();
}
?>
</a>
</span>
<h2 class="post-title"><?php the_title(); ?></h2>
<span class="post-category"><?php the_category(', ');?></span>
</li>
<?php endwhile; ?>
<?php endif; ?>
</ul>
<nav>
<?php
global $wp_query; // you can remove this line if everything works for you
// don't display the button if there are not enough posts
if ( $wp_query->max_num_pages > 1 )
echo '
<div class="wordpress_wrapper">
<div class="wordpress_loadmore">More posts</div>
</div>'; // you can use <a> as well
?>
</nav>
<?php wp_reset_postdata(); ?>
Clicking the button to load more posts results in following message:
https://www.uvjagtpro.dk/wp-admin/admin-ajax.php
jquery.js?ver=1.12.4:4 POST https://www.uvjagtpro.dk/wp-admin/admin-ajax.php 400 ()
send # jquery.js?ver=1.12.4:4
ajax # jquery.js?ver=1.12.4:4
(anonymous) # myloadmore.js:13
dispatch # jquery.js?ver=1.12.4:3
r.handle # jquery.js?ver=1.12.4:3
Why can't I parse variable in Array named "wordpress_loadmore_params.ajaxurl" without it causing a 400 bad request?
Link to page is here - https://www.uvjagtpro.dk/arkiv/
There are only 3 cases where WordPress will return a 400 on an AJAX request to
.../wp-admin/admin-ajax.php
$_REQUEST['action'] variable is empty
has_action( 'wp_ajax_' . $_REQUEST['action'] ) is false
has_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] ) is false
So, you should verify that your code
add_action('wp_ajax_loadmore', 'wordpress_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmore', 'wordpress_loadmore_ajax_handler');
is really executed and the query does contain a $_REQUEST['action'] with contents 'loadmore'. This is easiest to do if you know how to use a PHP debugger otherwise I would use error_log() to display relevant messages after the add_action statements. You can also display the value of the has_action() functions.
Your code looks correct to me so I think the error is not the code itself but maybe its location.

How to pass Select value from Javascript to PHP to generate select option on change

This is my code which generates locations:
<select name="filter-location" id="location">
<option value="">
<?php if ( $input_titles == 'placeholders' ) : ?>
<?php echo __( 'Location', 'realia' ); ?>
<?php else: ?>
<?php echo __( 'All locations', 'realia' ); ?>
<?php endif; ?>
</option>
<?php
$locations = get_terms('locations', array(
'hide_empty' => false,
'parent' => 0
));
?>
<?php if ( is_array( $locations ) ) : ?>
<?php foreach ( $locations as $location ) : ?>
<option value="
<?php echo esc_attr( $location->term_id ); ?>"
<?php if ( ! empty( $_GET['filter-location'] ) && $_GET['filter-location'] == $location->term_id ) : ?>selected="selected"
<?php endif; ?>>
<?php echo esc_html( $location->name ); ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
And this is the code which generates districts:
<?php $sublocations = get_terms('locations', array(
'hide_empty' => false,
'parent' => $location->term_id,
));
?>
As you can see, to generate districts, it needs $location->term_id.
How can I send $location->term_id whenever someone selects a location?
On changing the location selection, the ajaxDistrictsRequest() function is called with the selected value passed as a parameter.
<select name="filter-location" id="location" onchange="ajaxDistrictsRequest(this.value)">
<option value="">
<?php
if ( $input_titles == 'placeholders' ) :
echo __( 'Location', 'realia' );
else:
echo __( 'All locations', 'realia' );
endif;
?>
</option>
<?php
$locations = get_terms('locations', array(
'hide_empty' => false,
'parent' => 0
));
if ( is_array( $locations ) ) :
foreach ( $locations as $location ) :
$selected = ((! empty( $_GET['filter-location'] ) && $_GET['filter-location'] == $location->term_id ) ? "selected" : "";
?>
<option value="<?php echo esc_attr( $location->term_id ); ?>"
<?php echo $selected ?>><?php echo esc_html( $location->name ); ?></option>
<?php
endforeach;
endif;
?>
</select>
<select name="filter-sub-location" id="district" disabled>
<option value="">
</select>
The following code uses jQuery to send an AJAX request to districts.php with the provided value as term_id.
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js">
<script type="text/javascript">
function ajaxDistrictsRequest(value) {
if (value) {
var districtSelect = document.getElementById('district');
// disable the #district list until it is populated by the response
districtSelect.disabled = true;
// make the ajax call to districts.php
$.ajax({
url: 'districts.php',
type: 'POST',
data: {
term_id : value
},
success: function (response) {
// populate the #districts option list with the result
districtSelect.innerHTML = response;
// enable the #district control
districtSelect.disabled = false;
}
});
}
});
</script>
For completeness here is a sample districts.php file which generates the options for the #district dropdown list:
<?php
if ( isset( $_POST['term_id'] ) ) :
$term_id = $_POST['term_id'];
// do database query
$sql = 'SELECT id, name FROM some_table WHERE term_id = :value';
$stmt = $dbh->prepare($sql);
$stmt->execute( array( ':value' => $term_id ) );
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) :
echo "<option value='" . $row['id'] . "'>" . $row['name'] . "</option>";
endforeach;
exit;
endif;
?>

Categories

Resources