Ajax wipes value of session variable - ajax

I recently added an Ajax-powered load more button that loads additional blog posts to my wordpress site. I used the tutorial listed here: https://rudrastyh.com/wordpress/load-more-posts-ajax.html, and it works, but I've ran into another problem.
I have a session variable that counts the current post number. I show 10 posts per page and the counter works for the initial 10. Then I call the next 10 with ajax and instead of counting to 11, 12, 13 etc, it goes back to 1. There's clearly a problem with passing the end value (10) from the template, to the ajax handler in functions. Anyone know what could be wrong? Everything works if I don't use ajax - it's really frustrating.
Template PHP
<?php $_SESSION['the_counter'] = 0; ?>
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
'posts_per_page' => 10,
'paged' => $paged
);
$my_query = new WP_Query($args);
if($my_query->have_posts()): while($my_query->have_posts()) : $my_query->the_post();
get_template_part( 'template-parts/post/content', get_post_format() );
endwhile;
else:
get_template_part( 'no-results', 'home' );
endif;
if ( $my_query->max_num_pages > 1 ){
echo '</a><div class="misha_loadmore">More posts</div>';
}?>
</div>
<script>var posts_myajax = '<?php echo json_encode( $my_query->query_vars ) ?>',
current_page_myajax = 1,
max_page_myajax = <?php echo $my_query->max_num_pages ?>
</script>
<script src="/loadmore.js"></script>
<?php $my_query = null;
wp_reset_postdata();?>
Ajax Handler in functions.php
function misha_loadmore_ajax_handler(){
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/post/content', get_post_format() );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; }
add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler');
Load More JS
jQuery(function($){
$('.misha_loadmore').click(function(){
var button = $(this),
data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
'page' : misha_loadmore_params.current_page
};
$.ajax({
url : misha_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().before(data); // insert new posts
misha_loadmore_params.current_page++;
if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});});
And this is the session code I have on the top of my blog post content template file. It increments the count by 1 for every post.
$counter = $_SESSION['the_counter'];
$counter++;
$_SESSION['the_counter'] = $counter;
At the bottom of the file, I include:
echo insert_counter($the_counter);

At a glance, I'm betting sessions aren't being set. Try adding this to your functions.php file.
add_action('init', function() {
if (!session_id()) {
session_start();
});
This will ensure that sessions are loading on every page. It's worth mentioning that sessions aren't the best way to persist data. I would recommend replacing the session with a cookie.

Related

Ajax Load More Custom Post type WordPress

I am trying to load more post calling out the custom post type with the taxonomy array to sort out the specfic post or all Magazine port. If you click Load More and there is no post to return, the user will recieve a message. As of now when I click the "Load More" button, it seems like the funciton just loops with not returning 3 more post.
Below I have written up the steps I have taken to execute WordPress Ajax load more post functionality.
First Step:
Created a page template called taxonomy-magazine-category.php that lives in my theme folder with the markup to display 3 post and load more button functionality to return 3 more post at each click until all post are returned.
<div class="post row">
<?php
$paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
$latests = new WP_Query(array(
'posts_per_page' => 3,
'post_type' => 'magazine',
));
while($latests->have_posts()): $latests->the_post(); //put the post card here ?>
<div class="col-12 col-sm-12 col-md-7 col-xl-9">
<div class="blog-article-cards list-articles">
<?php
get_template_part('/components/magazine-article-card', null, array( 'magazines' => $magazines[$i], 'style' => 'regular'));
?>
</div>
</div>
<?php endwhile; ?>
</div>
<script>
var limit = 3,
page = 1,
type = 'latest',
category = '',
max_pages_latest = <?php echo $latests->max_num_pages ?>
</script>
<?php if ( $latests->max_num_pages > 1 ){
echo '<div class="load_more text-center">
Load More
</div>';
} else { ?>
<article>
<h1>Sorry...</h1>
<p><?php _e('Sorry, No Posts Available !'); ?></p>
</article>
<?php } wp_reset_query(); ?>
<?php get_footer(); ?>
Second Step:
Developed the function filter snippet of script at the bottom of the functions.php file that lives in /themes/understrap-child. The top function loads the Ajax files in WordPress installation including the custom Ajax file I have created which is in step three. The second function retuns the the post from the ajax handler.
function bsubash_load_more_scripts() {
wp_enqueue_script('jquery');
wp_register_script( 'loadmore_script', get_stylesheet_directory_uri() . '/js/ajax.js', array('jquery') );
wp_localize_script( 'loadmore_script', 'loadmore_params', array(
'ajaxurl' => admin_url('admin-ajax.php'),
) );
wp_enqueue_script( 'loadmore_script' );
}
add_action( 'wp_enqueue_scripts','bsubash_load_more_scripts' );
function bsubash_loadmore_ajax_handler(){
$type = $_POST['type'];
$category = isset($_POST['category']) ? $_POST['category']: '';
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
$args['posts_per_page'] = $_POST['limit'];
if($type == 'archive'){
$args['category_name'] = $category;
}
query_posts( $args );
if( have_posts() ) :
while(have_posts()): the_post();
//write your single post card
the_title();
the_excerpt();
endwhile;
endif;
die;
}
add_action('wp_ajax_loadmore','bsubash_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmore','bsubash_loadmore_ajax_handler');
Final Step:
Created an ajax.js file that lives in my theme folder /js/ajax.js which you will see in the funciton at step two. The ajax will not return the post after you click load more including displaying loading and load more static messages. This seems to be working fine.
jQuery(function($) {
$('.btn-load-more').click(function(e) {
e.preventDefault();
var button = $(this),
data = {
'action': 'loadmore',
'limit': limit,
'page': page,
'type': type,
'category': category
};
$.ajax({
url: loadmore_params.ajaxurl,
data: data,
type: 'POST',
beforeSend: function(xhr) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success: function(data) {
if (data) {
$(".latest_posts_wrapper").append(data);
page++;
button.text('Load More');
if (page == max_pages_latest)
button.remove(); // if last page, remove the button
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
});
All Done!!!
**
What is in my template file?**
Above, at the top of my page template, I have other post appearing that are featured post. These post are returning from the proxy. I am just pointing this out so you are aware of what is in my file as well. This isn't impacting my issue.
$magazines = [];
$wp_query = new WP_Query(
array(
'post_type' => 'Magazine',
'tax_query' => array(
array (
'taxonomy' => 'magazine_categories',
'field' => $categoryId,
'terms' => $category,
'posts_per_page' => $postsPerPage,
)
),
)
);
while ($wp_query->have_posts()) : $wp_query->the_post();
//$blogProxy = new BlogProxy(get_the_ID());
$magazine = new Magazine();
$magazine->title = get_the_title();
$magazine->featured_image = get_the_post_thumbnail_url(get_the_ID());
$magazine->preview_text = get_the_excerpt();
$magazine->permalink = get_the_permalink();
$magazine->date = get_the_date();
array_push($magazines, $magazine);
endwhile;
wp_reset_postdata();
?>
My goal is to develop a load more button with a custom post type using AJAX. If you follow the steps above you should see an active functionality that doesn't return post after clicking the load more button.
/* myloadmore.js */
jQuery(function($){ // use jQuery code inside this to avoid "$ is not defined" error
$('.misha_loadmore').click(function(){
var button = $(this),
data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
'page' : misha_loadmore_params.current_page
};
$.ajax({ // you can also use $.post here
url : misha_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().before(data); // insert new posts
misha_loadmore_params.current_page++;
if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
});
/* To style the button the according way use CSS below. */
.misha_loadmore{
background-color: #ddd;
border-radius: 2px;
display: block;
text-align: center;
font-size: 14px;
font-size: 0.875rem;
font-weight: 800;
letter-spacing:1px;
cursor:pointer;
text-transform: uppercase;
padding: 10px 0;
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out, color 0.3s ease-in-out;
}
.misha_loadmore:hover{
background-color: #767676;
color: #fff;
}
This is the AJAX handler function. Insert it to your functions.php file.
/* Enqueue jQuery and myloadmore.js. Pass query parameters to the script. */
function misha_my_load_more_scripts() {
global $wp_query;
// In most cases it is already included on the page and this line can be removed
wp_enqueue_script('jquery');
// register our main script but do not enqueue it yet
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/myloadmore.js', array('jquery') );
// now the most interesting part
// we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP
// you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script()
wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here
'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', 'misha_my_load_more_scripts' );
function misha_loadmore_ajax_handler(){
// prepare our arguments for the query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
// it is always better to use WP_Query but not here
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/post/content', get_post_format() );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; // here we exit the script and even no wp_reset_query() required!
}
add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}

Stripe payments are not working if I load Woocommerce checkout via AJAX

I'm trying to load Woocommerce checkout form via Ajax on a custom landing page so that it can have an instant checkout for the visitor.
I'm using the following code:
PHP function for AJAX:
add_action( 'wp_ajax_getCheckoutPageContent', 'getCheckoutPageContentCallBack' );
add_action( 'wp_ajax_nopriv_getCheckoutPageContent', 'getCheckoutPageContentCallBack' );
function getCheckoutPageContentCallBack() {
$product_id = absint( $_POST['product_id'] );
$quantity = absint( $_POST['quantity'] );
$product_status = get_post_status( $product_id );
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
if ( WC()->cart->add_to_cart( $product_id, $quantity ) ) {
do_action( 'woocommerce_ajax_added_to_cart', $product_id );
global $woocommerce;
$items = $woocommerce->cart->get_cart();
wc_setcookie( 'woocommerce_items_in_cart', count( $items ) );
wc_setcookie( 'woocommerce_cart_hash', md5( json_encode( $items ) ) );
do_action( 'woocommerce_set_cart_cookies', true );
define( 'WOOCOMMERCE_CHECKOUT', true );
echo do_shortcode('[woocommerce_checkout]');
}else{
define( 'WOOCOMMERCE_CHECKOUT', true );
echo do_shortcode('[woocommerce_checkout]');
}
die();
}
Javascrip code:
var wp_ajax_url= myAjax.ajaxurl;
var data = {
action: 'getCheckoutPageContent',
product_id: $('#land_prod_id').val(),
quantity: 1
};
jQuery.post( wp_ajax_url, data, function(content) {
jQuery("#buy_form_location").html(content);
});
} else{
All payment methods work except for Stripe where I get redirected to the actual checkout page, with the following error: Payment processing failed. Please retry.
On the regular checkout page the payment works, but I'd like it to work on the one loaded via AJAX too.
I'm using this plugin: woocommerce.com/products/stripe

Custom sort products via AJAX in Woocommerce

I have standard shop page. There I had made a custom sort via ajax. Everything works fine. But there is default pagination links, and when I sort products there links are not rebuild. How I can fix it?
PHP:
query_posts( $args );
if( have_posts() ) :
while( have_posts() ): the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
endif;
wp_reset_postdata();
die;
JS:
$.ajax({
url : orderby_params.ajaxurl,
data : data,
type : 'POST',
beforeSend : function(xhr){
},
success : function(data){
if(data){
$('ul.products').html(data);
}
}
});
I had tried use new WP_Query

How to add numeric pagination to Ajax result, that shows podcasts(custom post) filter by custom taxonomies

i would like to add numeric pagination (and load the posts dynamically) to this page, called 'page-podcast', where i filter, with Ajax call, my podcast (custom post), using these tags, genre, country and type: https://imgur.com/Qw8JOlC.
In my front end, page-podcast.php, i have this div, where post appears:
<div id="datafetch">Search results will appear here</div>
And in page function.php i added the function that call Ajax
add_action( 'wp_footer', 'ajax_fetch' );
function ajax_fetch() {
?>
<script type="text/javascript">
function fetch(e){
jQuery.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'post',
data: { action: 'data_fetch', keyword: keywords},
success: function(data) {
jQuery('#datafetch').html( data );
}
});
}
</script>
The following code is the ajax function (always on function.php):
add_action('wp_ajax_data_fetch' , 'data_fetch');
add_action('wp_ajax_nopriv_data_fetch','data_fetch');
function data_fetch(){
...filter part, omitted, because it has nothing to do with the question...
$the_query = new WP_Query($query_args);
if( $the_query->have_posts() ) :
while( $the_query->have_posts() ): $the_query->the_post(); ?>
<h2><?php the_title();?></h2>
<?php endwhile;
else: ?>
<p class="no-criteria"><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php
wp_reset_postdata();
endif;
die();
}
Someone has some tips/examples/code to share? Because i tried many solution that i find on the web, but nothing works.
Resolved.
So, i have added the number of the pages within the ajax function, before the end of the loop:
<?php if ($numberPages > 1): ?>
<ul>
<?php
for ($i = 1; $i <= $numberPages; $i++) {
echo '<li><a name="page" href="#" class="pagination" value="' . $i . '">'
. $i . '</a></li>';
}
?>
</ul>
$numberPages is equal to:
$the_query = new WP_Query($query_args);
$numberPages = $the_query->max_num_pages;
I create a global variable, call $page, set to 0.
Then i worked on my two event:
$(document).on("click touchend", ".premuto", function (event) {
event.preventDefault();
page = 1;
keywords['page'] = page;
keywords[$(this).attr('name')] = $(this).attr('value');
fetch(this);
});
$(document).on("click touchend", ".pagination", function (event) {
event.preventDefault();
keywords[$(this).attr('name')] = $(this).attr('value');
fetch(this);
});
".premuto" is an element that contain the id i want to pass to ajax (custom taxonomy) and page is set to 1.
".pagination" is the list of post's page number (1,2,...).
Finally, on my ajax function, i get the page number:
$paged = $_POST['keyword']['page'];
and in my wp_query i added:
'posts_per_page' => '2',
'paged' => $paged,

How can I activate Woocommerce Product Gallery in ajax container?

The new product gallery in Woocommerce is great, but unfortunately I can't get it to work outside the single product template page.
I'm using ajax to load in products in a container on my front page. The ajax call displays the product page: echo do_shortcode('[product_page id="' . $post_id . '"]');. The markup for the gallery is correct, but the .woocommerce-product-gallery container is marked with opacity: 0; and none of the scripts for the gallery is loaded.
How can I implement the gallery functionality with the ajax call and get it working?
Full ajax call:
JQuery
$('.product-modal-toggle').on('click',function(){
var theId = $(this).data('product-id');
var plagg = $(this).data('plagg');
var outfitEnkeltPlaggContainer = $('.outfit-enkelt-plagg');
var parentOutfit = $(this).closest('.outfit').attr('id');
var outfitDescendantContainer = $('#' + parentOutfit + ' .outfit-enkelt-plagg');
$.post('wp-admin/admin-ajax.php', {
action:'my_get_posts',
post_id: theId
}, function(data) {
console.log(data);
outfitDescendantContainer.html(data);
});
});
PHP
/*
** Get Woocommerce Products with Ajax.
** Display Product inside outfit container
*/
function my_get_posts_return() {
global $post;
$post_id = intval(isset($_POST['post_id']) ? $_POST['post_id'] : 0);
if ($post_id > 0) {
$the_query = new WP_query(array('p' => $post_id, 'post_type' => 'product'));
if ($the_query->have_posts()) {
while ($the_query->have_posts()) : $the_query->the_post();
$product = wc_get_product($post_id);
?>
<button class="close-plagg" type="button" name="close-plagg">
<img src="<?php echo get_template_directory_uri(); ?>/library/images/close.svg" alt="Close plagg">
</button>
<?php
echo do_shortcode('[product_page id="' . $post_id . '"]');
// wc_get_template_part( 'content', 'single-product' );
endwhile;
} else {
echo "There were no posts found";
}
}
wp_die();
}
add_action('wp_ajax_my_get_posts', 'my_get_posts_return');
add_action('wp_ajax_nopriv_my_get_posts', 'my_get_posts_return');
PHP
You have to enqueue the scripts of the gallery on your home page :
add_action( 'wp_enqueue_scripts', function(){
if( is_front_page() ){
wp_enqueue_script('zoom');
wp_enqueue_script('flexslider');
wp_enqueue_script('photoswipe-ui-default');
}
});
JS
In the success function of your $.postyou have to call the script :
$( '.woocommerce-product-gallery', data ).each( function() {
$( this ).wc_product_gallery();
} );
Hope this helps

Resources