I managed to build a ajax load more following this tutorial.
I managed to make it work for my blog post on my blog page. So I didn't change anything.
Now I try to make the same for my custom post type, so I simply duplicate all code, changing the variable names :
Here is my custom post type archive page:
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'post_type' =>'formation',
'posts_per_page' =>5,
'paged' => $paged
);
$query = new WP_Query( $args ); //Check the WP_Query docs to see how you can limit which posts to display ?>
<?php if ( $query->have_posts() ) : ?>
<div id="cc_formation_wrap" class="flex-row">
<?php while ( $query->have_posts() ) : $query->the_post();
$termsArray = get_the_terms( $post->ID, "categories-formations" ); //Get the terms for this particular item
$termsString = ""; //initialize the string that will contain the terms
foreach ( $termsArray as $term ) { // for each term
$termsString .= $term->slug.' '; //create a string that has all the slugs } ?>
<div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="isotope-thumbnail">
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('masonryLayout');
}; ?>
</div>
<div class="isotope-title">
<h3><?php the_title(); ?></h3>
</div>
<div class="entry-meta">
<?php if(get_field('duree')){
$duree = get_field_object('duree');
echo '<div><span class="isotope-duree">' . get_field('duree') . '</span></div>';}?>
</div>
<div class="isotope-excerpt">
<?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
</div>
<div class="isotope-cta">
Voir
</div>
</article>
</div>
<!-- end item -->
<?php endwhile; ?>
</div>
<!-- end isotope-list -->
<?php
global $wp_query;
if ( $wp_query->max_num_pages > 1 ) :
echo '<div id="cc_formation_loadmore">More posts</div>';
endif;
else :
get_template_part( 'template-parts/content', 'none' );
endif; ?>
Here is the code for functions.php file :
/*FITLERING AND LOADING MORE ON FORMATION PAGE*/
add_action( 'wp_enqueue_scripts', 'cc_formation_script_and_styles');
function cc_formation_script_and_styles() {
if( is_post_type_archive('formation') ){
global $wp_query;
wp_register_script( 'load-more', get_stylesheet_directory_uri() . '/js/load-more.js', array('jquery') );
wp_localize_script( 'load-more', 'cc_formation_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' => $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1,
'max_page' =>$wp_query->max_num_pages
) );
wp_enqueue_script( 'load-more' );
}
}
add_action('wp_ajax_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');
function cc_formation_loadmore_ajax_handler(){
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
$args["post_type"] = 'formation';
query_posts( $args );
if( have_posts() ) :
while( have_posts() ): the_post();
$termsArray = get_the_terms($post->ID, "categories-formations");
$termsString ="";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="isotope-thumbnail">
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('masonryLayout');
} ;
?>
</div>
<div class="isotope-title">
<h3><?php the_title(); ?></h3>
</div>
<div class="isotope-excerpt">
<?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
</div>
<div class="isotope-cta">
Voir
</div>
</article>
</div> <!-- end item -->
<?php
endwhile;
endif;
die;
}
add_action('wp_ajax_ccformationfilter', 'cc_formation_filter_function');
add_action('wp_ajax_nopriv_ccformationfilter', 'cc_formation_filter_function');
function cc_formation_filter_function(){
$args = array(
'post_type' => 'formation',
'post_per_page'=>5,
'tax_query' => array(
array(
'taxonomy' => 'categories-formations',
'field' => 'slug',
'terms' => array('git','python','django','unix')
)
),
);
// run the query
query_posts( $args );
if( have_posts() ) :
ob_start();
while( have_posts() ): the_post();
$termsArray = get_the_terms($post->ID, "categories-formations");
$termsString ="";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="isotope-thumbnail">
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('masonryLayout');
}
?>
</div>
<div class="isotope-title">
<h3><?php the_title(); ?></h3>
</div>
<div class="entry-meta">
<?php if(get_field('duree')){
$duree = get_field_object('duree');
echo '<div><span class="isotope-duree">' . get_field('duree') . '</span></div>';
}
?>
</div>
<div class="isotope-excerpt">
<?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
</div>
<div class="isotope-cta">
Voir
</div>
</article>
</div> <!-- end item -->
<?php
endwhile;
$posts_html = ob_get_contents();
ob_end_clean();
else:
$posts_html = '<p>Nothing found for your criteria.</p>';
endif;
echo json_encode( array(
'posts' => json_encode( $wp_query->query_vars ),
'max_page' => $wp_query->max_num_pages,
'found_posts' => $wp_query->found_posts,
'content' => $posts_html
) );
die();
}
So I changed the ajax action name, the params function etc. I kept the global wp_query but don't know if I also have to change that.
Then in a separate js file I put the following :
jQuery(function($){
/* LOAD MORE FUNCTION ON FORMATION ARCHIVE PAGE */
$('#cc_formation_loadmore').click(function(){
$.ajax({
url : cc_formation_loadmore_params.ajaxurl, // AJAX handler
data : {
'action': 'loadmoreformationbutton', // the parameter for admin-ajax.php
'query': cc_formation_loadmore_params.posts, // loop parameters passed by wp_localize_script()
'page' : cc_formation_loadmore_params.current_page // current page
},
type : 'POST',
beforeSend : function ( xhr ) {
$('#cc_formation_loadmore').text('Loading...'); // some type of preloader
},
success : function( posts ){
if( posts ) {
$('#cc_formation_loadmore').text( 'More posts' );
$('#cc_formation_wrap').append( posts ); // insert new posts
cc_formation_loadmore_params.current_page++;
if ( cc_formation_loadmore_params.current_page == cc_formation_loadmore_params.max_page )
$('#cc_formation_loadmore').hide(); // if last page, HIDE the button
} else {
$('#cc_formation_loadmore').hide(); // if no data, HIDE the button as well
}
}
});
return false;
});
/* FILTERING FUNCTION ON FORMATION ARCHIVE PAGE */
$('#formation_filters').change(function(){
$.ajax({
url : cc_formation_loadmore_params.ajaxurl,
data : $('#formation_filters').serialize(), // form data
dataType : 'json', // this data type allows us to receive objects from the server
type : 'POST',
success : function( data ){
// when filter applied:
// set the current page to 1
cc_formation_loadmore_params.current_page = 1;
// set the new query parameters
cc_formation_loadmore_params.posts = data.posts;
// set the new max page parameter
cc_formation_loadmore_params.max_page = data.max_page;
// change the button label back
// insert the posts to the container
$('#cc_formation_wrap').html(data.content);
// hide load more button, if there are not enough posts for the second page
if ( data.max_page < 2 ) {
$('#cc_formation_loadmore').hide();
} else {
$('#cc_formation_loadmore').show();
}
}
});
// do not submit the form
return false;
});
});
With this, the load more works. It displays the next custom posts type on my archive page.
But the filtering function doens't work.
So I need help to understand which variables I have to change. When I click on a filter checkbox, it first loads my blog post, and then the others filtering chekcbox don't work.
So I don't understand why it calls my blog posts.. What am I doing wrong ????
Looking for advice on this.
Thanks
Ok i finaly found my solultion !
1-In my project I first build a blog page (with normal blog posts) with categories filters and an ajax load more button.
Here is the code in my home.php
<?php
/**
* The main template file
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
*
* #link https://developer.wordpress.org/themes/basics/template-hierarchy/
*
* #package mysite
*/
get_header();
?>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<div class="flex-container">
<div class="flex-row">
<header class="page-header">
<?php
single_post_title('<h1 class="page-title">', '</h1>' );
?>
</header><!-- .page-header -->
</div>
<div class="flex-row">
<form action="#" method="POST" id="post_filters">
<p>Clear</p>
<?php
if( $terms = get_terms( array( 'taxonomy' => 'category' ) ) ) :
foreach( $terms as $term ) :
echo '<p><input type="radio" id="' . $term->term_id . '" value="' . $term->term_id . '" name="category_filters" class="category_filter"/><label for="' . $term->term_id. '">' . $term->name . '</label></p>';
endforeach;
endif;
?>
<!-- required hidden field for admin-ajax.php -->
<input type="hidden" name="action" value="ccfilter" />
</form>
</div>
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 5,
'paged' => $paged
);
$query = new WP_Query( $args ); ?>
<?php
if ( $query->have_posts() ) :
$count = (int)0;?>
<div id="cc_posts_wrap" class="flex-row">
<?php
while ( $query->have_posts() ) : $count++;
$query->the_post();
if($count == 1){
$span = 'flex-col-xs-12';
$limit = 20;
}
if($count == 2 || $count == 3){
$span = 'flex-col-sm-6';
$limit = 13;
}
if($count > 3){
$span = 'flex-col-sm-4';
$limit = 13;
}
//If its not 3 or higher, increase the count
$termsArray = get_the_terms($post->ID, "category"); //Get the terms for this particular item
$termsString =""; //initialize the string that will contain the terms
foreach ( $termsArray as $term ) { // for each term
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString .' ' . $span ;?> item">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="post-featured-thumbnail">
<?php
if ( has_post_thumbnail() ) {
if($count == 1){
the_post_thumbnail('blog_featured');
}else{
the_post_thumbnail();
}
}
if ( 'post' === get_post_type() ) :
?>
<div class="entry-meta">
<?php
category_sticker();
?>
</div><!-- .entry-meta -->
<?php endif; ?>
</div>
<div class="post-content">
<header class="entry-header">
<?php
if ( is_singular() ) :
the_title( '<h1 class="entry-title">', '</h1>' );
else :
the_title( '<h2 class="entry-title">', '</h2>' );
endif;
?>
</header><!-- .entry-header -->
<div class="entry-content">
<?php echo excerpt($limit); ?>
</div><!-- .entry-content -->
</div>
</article><!-- #post-<?php the_ID(); ?> -->
</div>
<?php endwhile;
?>
</div> <!-- end isotope-list -->
<?php global $wp_query; // you can remove this line if everything works for you
if ( $wp_query->max_num_pages > 1 ) :
echo '<div id="cc_loadmore">More posts</div>'; // you can use <a> as well
endif;
else :
get_template_part( 'template-parts/content', 'none' );
endif;
?>
</div>
</main><!-- #main -->
</div><!-- #primary -->
<?php
get_footer();
Then in function php, the code for the load more button and the filters functions :
/*FUNCTION FILTER AND AJAX LOAD MORE*/
add_action( 'wp_enqueue_scripts', 'cc_script_and_styles');
function cc_script_and_styles() {
if ( is_home() ) {
global $wp_query;
wp_register_script( 'cc_scripts', get_stylesheet_directory_uri() . '/js/script.js', array('jquery') );
wp_localize_script( 'cc_scripts', 'cc_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' => $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1,
'max_page' => $wp_query->max_num_pages
) );
wp_enqueue_script( 'cc_scripts' );
}
}
add_action('wp_ajax_loadmorebutton', 'cc_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmorebutton', 'cc_loadmore_ajax_handler');
function cc_loadmore_ajax_handler(){
$params = json_decode( stripslashes( $_POST['query'] ), true );
$params['paged'] = $_POST['page'] + 1;
$params['post_status'] = 'publish';
query_posts( $params );
if( have_posts() ) :
while( have_posts() ): the_post();
$termsArray = get_the_terms($post->ID, "category");
$termsString ="";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString ;?> flex-col-sm-4 item">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="post-featured-thumbnail">
<?php
if ( has_post_thumbnail() ) {
if($count == 1){
the_post_thumbnail('blog_featured');
}else{
the_post_thumbnail();
}
}
;
if ( 'post' === get_post_type() ) :
?>
<div class="entry-meta">
<?php
category_sticker();
?>
</div><!-- .entry-meta -->
<?php endif; ?>
</div>
<div class="post-content">
<header class="entry-header">
<?php
if ( is_singular() ) :
the_title( '<h1 class="entry-title">', '</h1>' );
else :
the_title( '<h2 class="entry-title">', '</h2>' );
endif;
?>
</header><!-- .entry-header -->
<div class="entry-content">
<?php echo excerpt($limit); ?>
</div><!-- .entry-content -->
</div>
</article><!-- #post-<?php the_ID(); ?> -->
</div>
<?php
endwhile;
endif;
die;
}
add_action('wp_ajax_ccfilter', 'cc_filter_function');
add_action('wp_ajax_nopriv_ccfilter', 'cc_filter_function');
function cc_filter_function(){
if( isset( $_POST['category_filters'] ) )
$args['tax_query'] = array(
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => $_POST['category_filters'],
"posts_per_page" => 5
)
);
query_posts( $args );
global $wp_query;
if( have_posts() ) : $count = (int)0;
ob_start();
while( have_posts() ): $count++;
the_post();
if($count == 1){
$span = 'flex-col-xs-12';
$limit = 20;
}
if($count == 2 || $count == 3){
$span = 'flex-col-sm-6';
$limit = 13;
}
if($count > 3){
$span = 'flex-col-sm-4';
$limit = 13;
}
$termsArray = get_the_terms($post->ID, "category");
$termsString ="";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString .' ' . $span ;?> item">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="post-featured-thumbnail">
<?php
if ( has_post_thumbnail() ) {
if($count == 1){
the_post_thumbnail('blog_featured');
}else{
the_post_thumbnail();
}
}
;
if ( 'post' === get_post_type() ) :
?>
<div class="entry-meta">
<?php
category_sticker();
?>
</div><!-- .entry-meta -->
<?php endif; ?>
</div>
<div class="post-content">
<header class="entry-header">
<?php
if ( is_singular() ) :
the_title( '<h1 class="entry-title">', '</h1>' );
else :
the_title( '<h2 class="entry-title">', '</h2>' );
endif;
?>
</header><!-- .entry-header -->
<div class="entry-content">
<?php echo excerpt($limit); ?>
</div><!-- .entry-content -->
</div>
</article><!-- #post-<?php the_ID(); ?> -->
</div>
<?php
endwhile;
$posts_html = ob_get_contents();
ob_end_clean();
else:
$posts_html = '<p>Nothing found for your criteria.</p>';
endif;
echo json_encode( array(
'posts' => json_encode( $wp_query->query_vars ),
'max_page' => $wp_query->max_num_pages,
'found_posts' => $wp_query->found_posts,
'content' => $posts_html
) );
die();
}
Then, in a separate js file, the functions for the load more button and filters function :
jQuery(function($){
/* LOAD MORE FUNCTION */
$('#cc_loadmore').click(function(){
$.ajax({
url : cc_loadmore_params.ajaxurl, // AJAX handler
data : {
'action': 'loadmorebutton', // the parameter for admin-ajax.php
'query': cc_loadmore_params.posts, // loop parameters passed by wp_localize_script()
'page' : cc_loadmore_params.current_page // current page
},
type : 'POST',
beforeSend : function ( xhr ) {
$('#cc_loadmore').text('Loading...'); // some type of preloader
},
success : function( posts ){
if( posts ) {
$('#cc_loadmore').text( 'More posts' );
$('#cc_posts_wrap').append( posts ); // insert new posts
cc_loadmore_params.current_page++;
if ( cc_loadmore_params.current_page == cc_loadmore_params.max_page )
$('#cc_loadmore').hide(); // if last page, HIDE the button
} else {
$('#cc_loadmore').hide(); // if no data, HIDE the button as well
}
}
});
return false;
});
/* FILTERING FUNCTION */
$('#post_filters').change(function(){
$.ajax({
url : cc_loadmore_params.ajaxurl,
data : $('#post_filters').serialize(), // form data
dataType : 'json', // this data type allows us to receive objects from the server
type : 'POST',
success : function( data ){
cc_loadmore_params.current_page = 1;
cc_loadmore_params.posts = data.posts;
cc_loadmore_params.max_page = data.max_page;
$('#cc_posts_wrap').html(data.content);
if ( data.max_page < 2 ) {
$('#cc_loadmore').hide();
} else {
$('#cc_loadmore').show();
}
}
});
return false;
}); });
For blog posts, it's done and it works !
Explanations :
As you can see here, in functions.php, and the cc_script_and_styles function, and the -'cc_loadmore_params' are used everywhere in the js file. Be careful to write the same function in all places!
The action of the ajax call in the js file, 'loadmorebutton', is the same name than in the hook 'wp_ajax_loadmorebutton' in functions.php
add_action('wp_ajax_loadmorebutton', 'cc_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmorebutton', 'cc_loadmore_ajax_handler');
The value of the hidden input in home.php : 'ccfilter' is the same than in the hook of the function cc_filter_function(){
and
add_action('wp_ajax_ccfilter', 'cc_filter_function');
add_action('wp_ajax_nopriv_ccfilter', 'cc_filter_function');
Now, we also want to add similar filters and a load more button for a custom post type.
Here is my custom post type archive :
get_header();
?>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<div class="flex-container">
<div class="flex-row">
<header class="page-header">
<?php
post_type_archive_title( '<h1 class="page-title">', '</h1>' );
?>
</header><!-- .page-header -->
</div>
<div class="flex-row">
<form action="#" method="POST" id="formation_filters">
<p>Clear</p>
<?php
if( $terms = get_terms( array( 'taxonomy' => 'categories-formations' ) ) ) :
foreach( $terms as $term ) :
echo '<p><input type="radio" id="' . $term->term_id . '" value="' . $term->term_id . '" name="category_formation_filters" class="category_formation_filters"/><label for="' . $term->term_id. '">' . $term->name . '</label></p>';
endforeach;
endif;
?>
<!-- required hidden field for admin-ajax.php -->
<input type="hidden" name="action" value="ccformationfilter" />
</form>
</div>
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'post_type' =>'formation',
'posts_per_page' =>5,
'paged' => $paged
);
$query = new WP_Query( $args );?>
<?php if ( $query->have_posts() ) : ?>
<div id="cc_formation_wrap" class="flex-row">
<?php while ( $query->have_posts() ) : $query->the_post();
$termsArray = get_the_terms( $post->ID, "categories-formations" );
$termsString = "";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug.' ';
}
?>
<div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="isotope-thumbnail">
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('masonryLayout');
} ;
?>
</div>
<div class="isotope-title">
<h3><?php the_title(); ?></h3>
</div>
<div class="entry-meta">
<?php if(get_field('duree')){
$duree = get_field_object('duree');
echo '<div><span class="isotope-duree">' . get_field('duree') . '</span></div>';
}
?>
</div>
<div class="isotope-excerpt">
<?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
</div>
<div class="isotope-cta">
Voir
</div>
</article>
</div> <!-- end item -->
<?php endwhile;
?>
</div> <!-- end isotope-list -->
<?php
if ( $query->max_num_pages > 1 ) :
echo '<div id="cc_formation_loadmore">More posts</div>';
endif;
else :
get_template_part( 'template-parts/content', 'none' );
endif; ?>
</div>
</main>
</div>
<script>
var posts_myajax = '<?php echo serialize( $query->query_vars ) ?>',
current_page_myajax = 1,
max_page_myajax = <?php echo $query->max_num_pages ?>
</script>
<script src="<?php bloginfo('template_url')?>/js/load-more.js"></script>
<?php get_footer();?>
Here we build the same type of filters, we just changed the name of the taxonomy, and declare the post_type parameter. We make our ajax call at the bottom of the file with new variables names. And we call a separate js file load-more.js.
In order to keep clean structure, I also created a separate file called : formation-query.php. In functions.php, I call it with:
require get_template_directory() . '/inc/formation-query.php';
We don't duplicate the function cc_script_and_styles() {
We just create our two functions for load more and filters with new variables names.
add_action('wp_ajax_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');
function cc_formation_loadmore_ajax_handler(){
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
$args["post_type"] = 'formation';
query_posts( $args );
global $wp_query;
if( have_posts() ) :
while( have_posts() ): the_post();
$termsArray = get_the_terms($post->ID, "categories-formations");
$termsString ="";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="isotope-thumbnail">
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('masonryLayout');
} ;
?>
</div>
<div class="isotope-title">
<h3><?php the_title(); ?></h3>
</div>
<div class="isotope-excerpt">
<?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
</div>
<div class="isotope-cta">
Voir
</div>
</article>
</div> <!-- end item -->
<?php
endwhile;
endif;
die;
}
add_action('wp_ajax_ccformationfilter', 'cc_formation_filter_function');
add_action('wp_ajax_nopriv_ccformationfilter', 'cc_formation_filter_function');
function cc_formation_filter_function(){
$args["post_type"] = 'formation';
$args['tax_query'] = array(
array(
'taxonomy' => 'categories-formations',
'field' => 'id',
'terms' => $_POST['category_formation_filters'],
"posts_per_page" => 5
)
);
$query = new WP_Query($args);
if( $query->have_posts() ) :
ob_start();
while( $query->have_posts() ): $query->the_post();
$termsArray = get_the_terms($post->ID, "categories-formations");
$termsString ="";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug;
}
?>
<div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
<article id="post-<?php the_ID(); ?>" <?php post_class();?>>
<div class="isotope-thumbnail">
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('masonryLayout');
}
?>
</div>
<div class="isotope-title">
<h3><?php the_title(); ?></h3>
</div>
<div class="entry-meta">
<?php if(get_field('duree')){
$duree = get_field_object('duree');
echo '<div><span class="isotope-duree">' . get_field('duree') . '</span></div>';
}
?>
</div>
<div class="isotope-excerpt">
<?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
</div>
<div class="isotope-cta">
Voir
</div>
</article>
</div> <!-- end item -->
<?php
endwhile;
$posts_html = ob_get_contents();
ob_end_clean();
else:
$posts_html = '<p>Nothing found for your criteria.</p>';
endif;
echo json_encode( array(
'posts' => json_encode( $query->query_vars ),
'max_page' => $query->max_num_pages,
'found_posts' => $query->found_posts,
'content' => $posts_html
) );
die();
}
Now in a separate load-more.js file :
/* LOAD MORE FUNCTION ON FORMATION ARCHIVE PAGE */
$('#cc_formation_loadmore').click(function(){
data = {
'action': 'loadmoreformationbutton',
'query': posts_myajax,
'page' : current_page_myajax
};
$.ajax({
url : '/mysite/wp-admin/admin-ajax.php', // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
$('#cc_formation_loadmore').text('Loading...');
},
success : function( posts ){
if( posts ) {
$('#cc_formation_loadmore').text( 'More posts' );
$('#cc_formation_wrap').append( posts );
current_page_myajax++;
if ( current_page_myajax == max_page_myajax )
$('#cc_formation_loadmore').hide();
} else {
$('#cc_formation_loadmore').hide();
}
}
});
return false;
});
/* FILTERING FUNCTION ON FORMATION ARCHIVE PAGE */
$('#formation_filters').change(function(){
$.ajax({
url : '/mysite/wp-admin/admin-ajax.php',
data : $('#formation_filters').serialize(),
dataType : 'json',
type : 'POST',
success : function( data ){
current_page_myajax = 1;
posts_myajax = data.posts;
max_page_myajax = data.max_page;
$('#cc_formation_wrap').html(data.content);
if ( data.max_page < 2 ) {
$('#cc_formation_loadmore').hide();
} else {
$('#cc_formation_loadmore').show();
}
}
});
return false;
});
});
As you can see,
The 'loadmoreformationbutton' in the hook is the ajax action name in the js file.
The value of hidden input in the form 'ccformationfilter' is the name of the filter ajax function.
Now you can duplicate this if you need others load more buttons and filters for other custom post type !
It took me a while before understanding that function names had to be the same in every file. The different loops are of course also important.
As an option, you could avoid PITA with your own code followed by tutorial by using the pre-built plugin to achieve Ajax Load More and filtering in Wordpress.
https://wordpress.org/plugins/ajax-load-more/
It's a really good one I've used multiple times to implement Load More by Ajax in my websites.
The free version has plenty of features.
please visit link1 , you can see there is option to find shipping is available or not for particular zip code : image1
here shipping charges are working for instock products but not for out-of -stock products.
Form.phtml
app/design/frontend/default/default/template/webdevlopers/productpageshipping/estimate/form.phtml
<?php if ($this->isFieldVisible('postcode')): ?>
<li class="item">
<label for="search"<?php if ($this->isFieldRequired('postcode')):?> class="required" <?php endif;?>>
<?php if ($this->isFieldRequired('postcode')):?>
<em>*</em>
<?php endif;?>
<?php echo Mage::helper('webdevlopers_productpageshipping')->__('') ?>
</label>
<div class="search">
<input placeholder="Enter your PIN Code"
class="input-text validate-postcode<?php if ($this->isFieldRequired('postcode')):?> required-entry<?php endif;?>"
type="text" id="estimate_postcode"
name="estimate[postcode]"
value="<?php echo $this->htmlEscape($this->getFieldValue('postcode')) ?>"
onkeydown="if (event.keyCode == 13) { return false;}" />
</div>
</li>
<?php endif; ?>
Script
<script type="text/javascript">
var $ = jQuery.noConflict();
(function($) {
$(document).ready(function(){
$('#estimate_postcode').keydown(function(e){
var items = $$(['.shipping-estimation-form input',
'.shipping-estimation-form select',
'#product_addtocart_form input',
'#product_addtocart_form select']);
var estimationUrl = '<?php echo $this->jsQuoteEscape($this->getEstimateUrl());?>';
var parameters = Form.serializeElements(items, true);
console.log("zipcode onkeypress worked");
if (!e) e = window.event;
var keyCode = e.keyCode || e.which;
if (keyCode == '13'){
//disable default enter action
e.preventDefault();
console.log("Enter button was pressed");
$('#shipping-estimate-loading-message').show();
$('#shipping-estimate-results').hide();
new Ajax.Updater('shipping-estimate-results', estimationUrl, {
parameters: parameters,
onComplete: function() {
console.log("ajax updater worked");
$('#shipping-estimate-loading-message').hide();
$('#shipping-estimate-results').show();
$('#unique_id').hide();
//$('unique_id').hide();
$('estimate_postcode').val()
}
});
};
});
});
}) ( jQuery );
function estimateProductShipping()
{
var estimationUrl = '<?php echo $this->jsQuoteEscape($this->getEstimateUrl());?>';
var items = $$(['.shipping-estimation-form input',
'.shipping-estimation-form select',
'#product_addtocart_form input',
'#product_addtocart_form select']);
var validationResult = true;
// Check the valid input
if (!items.map(Validation.validate).all()) {
return;
}
var parameters = Form.serializeElements(items, true);
$('shipping-estimate-loading-message').show();
$('shipping-estimate-results').hide();
new Ajax.Updater('shipping-estimate-results', estimationUrl, {
parameters: parameters,
onComplete: function() {
console.log("ajax updater worked");
$('shipping-estimate-loading-message').hide();
$('shipping-estimate-results').show();
// $('#unique_id').hide();
$('unique_id').hide();
$('estimate_postcode').val()
}
});
}
//]]>
</script>
complete code of the file : https://gist.github.com/anonymous/ebe868508b2c21e9c032
result.phtml
app/design/frontend/default/default/template/webdevlopers/productpageshipping/estimate/result.phtml
<div class="block block-shipping-estimate block-shipping-results">
<div class="block-title">
<strong><span>
<?php echo Mage::helper('webdevlopers_productpageshipping')->getShiptitle(); ?>
</span></strong>
</div>
<div class="block-content">
<?php if ($this->getResult()):?>
<dl>
<?php foreach ($this->getResult() as $code => $_rates): ?>
<dt><?php echo $this->getCarrierName($code) ?></dt>
<dd>
<ul>
<?php foreach ($_rates as $_rate): ?>
<li<?php if ($_rate->getErrorMessage()) echo ' class="error-msg"';?>>
<?php if ($_rate->getErrorMessage()): ?>
<?php echo $_rate->getErrorMessage() ?>
<?php else: ?>
<?php
// echo $_rate->getMethodTitle()
?>
<?php $_excl = $this->getShippingPrice($_rate->getPrice(), $this->helper('tax')->displayShippingPriceIncludingTax()); ?>
<?php $_incl = $this->getShippingPrice($_rate->getPrice(), true); ?>
<!-- sat -->
<p>
<?php echo "Shipping is available";?>
</p>
<p class="vship1">
<?php echo "Selling Price + " . str_replace('.00','',$_excl) . " Delivery ";?>
</p>
<!-- sat -->
<?php if ($this->helper('tax')->displayShippingBothPrices() && $_incl != $_excl): ?>
(<?php echo Mage::helper('webdevlopers_productpageshipping')->__('Incl. Tax'); ?> <?php echo $_incl; ?>)
<?php endif; ?>
<?php endif ?>
</li>
<?php endforeach; ?>
</ul>
</dd>
<?php endforeach; ?>
</dl>
<?php else: ?>
<?php //echo $this->getMessagesBlock()->toHtml(); ?>
<?php echo Mage::helper('webdevlopers_productpageshipping')->getResult(); ?>
<?php endif;?>
</div>
</div>
app/code/community/webdevolopers/productpageshiping/Block/estimate/ Result.php
<?php
class WebDevlopers_ProductPageShipping_Block_Estimate_Result extends WebDevlopers_ProductPageShipping_Block_Estimate_Abstract
{
public function getResult()
{
return $this->getEstimate()->getResult();
}
public function hasResult()
{
return $this->getResult() !== null;
}
public function getCarrierName($code)
{
$carrier = Mage::getSingleton('shipping/config')->getCarrierInstance($code);
if ($carrier) {
return $carrier->getConfigData('title');
}
return null;
}
public function getShippingPrice($price, $flag)
{
return $this->formatPrice(
$this->helper('tax')->getShippingPrice(
$price,
$flag,
$this->getEstimate()
->getQuote()
->getShippingAddress()
)
);
}
public function formatPrice($price)
{
return $this->getEstimate()
->getQuote()
->getStore()
->convertPrice($price, true);
}
}
changing the settings in System > Config > Inventory
Easiest way to do this is select all products you want to allow to be backordered, then select Update attributes from the actions drop down and click submit. then shipping problem will not be problem.
I am using opencart version 2.0.2.0 and now i am trying to get image or image url in manufacturer page.
I have added the code in catalog/controller/product/manufacturer.php
$manufacturer_image = $this->model_catalog_manufacturer->getManufacturer($manufacturer_id);
if($manufacturer_image){
$this->data['manufacturers_img'] = $this->model_tool_image->resize($manufacturer_image['image'], 120, 120);
}else{
$this->data['manufacturers_img'] = false;
}
and call it in catalog/view/theme/default/template/product/manufacturer_list.tpl
<div class="row">
<?php foreach ($manufacturers as $manufacturer) { ?>
<div class="col-sm-3"><?php echo $manufacturer['name']; ?>
<?php echo ($manufacturers_img) ? '<img src="'.$manufacturers_img.'" alt="'.$manufacturers.'" />' : $manufacturers ;?><br />
</div>
<?php } ?>
</div>
But it's getting error in my /index.php?route=product/manufacturer page
Notice: Undefined variable: manufacturers_img in
/data1/opencart-2.0.2.0/catalog/view/theme/default/template/product/manufacturer_list.tpl
on line 32Array
lets be clear ControllerProductManufacturer index() shows list and info() shows detail of the mfg,
//catalog/controller/product/manufacturer.php:46
Replace
$data['categories'][$key]['manufacturer'][] = array(
with
$manufacturer_image = $this->model_catalog_manufacturer->getManufacturer($result['manufacturer_id']);
if($manufacturer_image){
$mfg_img = $this->model_tool_image->resize($manufacturer_image['image'], 120, 120);
}else{
$mfg_img = false;
}
$data['categories'][$key]['manufacturer'][] = array(
'image'=>$mfg_img,
And in catalog/view/theme/default/template/product/manufacturer_list.tpl:30
inside loop
<?php if($manufacturer['image']):?>
<img src="<?php echo $manufacturer['image']; ?>" alt="<?php echo $manufacturer['name'];?>">
<?php endif;?>
i'm loading a post with ajax.
The code is
$(document).ready(function(){
loadPostsFun = function(){
$.ajax({
url: "http://lab1.koalamedia.es/ajax/",
//url: "/random/",
success: function(response){
$("#randomPost").html( response );
}
});
};
$("#another").click(function(){
loadPostsFun();
return false;
});
});
The response is generated by a custom template with this code:
<?php
query_posts('showposts=1&orderby=rand');
the_post();
$args = array( 'numberposts' => 1, 'orderby' => 'date' );
$rand_posts = get_posts( $args );
?>
<?php
foreach( $rand_posts as $post ) : setup_postdata($post);
?>
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php if ( is_front_page() ) { ?>
<h2 class="entry-title"><?php the_title(); ?></h2>
<?php } else { ?>
<h1 class="entry-title"><?php the_title(); ?></h1>
<?php } ?>
<div class="entry-content">
<?php the_content(); ?>
<?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
<?php comments_popup_link(__('Comments (0)'), __('Comments (1)'), __('Comments (%)')); ?>
</div><!-- .entry-content -->
</div><!-- #post-## -->
<?php
//comments_template( '', true ); //this doesn't work
comment_form();
//wp_list_comments(''); //this doesn't work
?>
<?php endforeach; ?>
The ajax request works but the comments doesn't show.All the post data is there.
How can i show the comments?
neither comments_template or wp_list_comments work.
You can view a demo or download the template sample i've done here
Without much tweaking wp_list_comments() works in a comments template (usually comments.php) only.
Use get_comments(), pass the post ID as parameter:
$comments = get_comments(array ( 'post_id' => $post->ID );
if ( $comments )
{
foreach ( $comments as $comment )
{
print "<li>$comment->comment_author<br>$comment->comment_content</li>";
}
}
i've found the problem, i forgot to set the global variable:
global $withcomments;
i was using
$withcomments = true;
comments_template();
but without the global it didn't work.
Now works like normal comments do.
I have the following problem:
I want develop Pagination with rel=“next” and rel=“prev” for magento product lists.
http://googlewebmastercentral.blogspot.com/2011/09/pagination-with-relnext-and-relprev.html
How can I access the pager in ? The head-block has been already rendered when the pager-block will be rendered...
Is there any solution for my problem?
Yes, you can do edit the following file:
/app/design/frontend//default/template/page/html/pager.phtml
There you see for example:
<?php if (!$this->isFirstPage()): ?>
<li>
<a class="previous<?php if(!$this->getAnchorTextForPrevious()): ?> i-previous<?php endif;?>" href="<?php echo $this->getPreviousPageUrl() ?>" title="<?php echo $this->__('Previous') ?>">
<?php echo $this->__("Previous");?>
</a>
</li>
<?php endif;?>
Where you can easily add the rel="..." you want to the link, same goes for the "Next" link ;)
I added this code into the head.phtml file...
<?php
$actionName = $this->getAction()->getFullActionName();
if($actionName == 'catalog_category_view') // Category Page
{
$id = Mage::app()->getRequest()->getParam('id', false); //cat id
$category = Mage::getModel('catalog/category')->load($id);
$prodCol = $category->getProductCollection();
$tool = $this->getLayout()->createBlock('catalog/product_list_toolbar')->setCollection($prodCol);
$linkPrev = false;
$linkNext = false;
if ($tool->getCollection()->getSize()) {
if ($tool->getLastPageNum() > 1) {
if (!$tool->isFirstPage()) {
$linkPrev = true;
$prevUrl = $tool->getPreviousPageUrl();
}
if (!$tool->isLastPage()) {
$linkNext = true;
$nextUrl = $tool->getNextPageUrl();
}
}
}
?>
<?php if ($linkPrev): ?>
<link rel="prev" href="<?php echo $prevUrl ?>" />
<?php endif; ?>
<?php if ($linkNext): ?>
<link rel="next" href="<?php echo $nextUrl ?>" />
<?php endif; ?>
<?php
}
?>
From version 1.5 this solution doesn't work anymore, this is my solution:
$actionName = $this->getAction()->getFullActionName();
if($actionName == 'catalog_category_view') // Category Page
{
$id = Mage::app()->getRequest()->getParam('id', false); //cat id
$category = Mage::getModel('catalog/category')->load($id);
$prodCol = $category->getProductCollection()->addAttributeToFilter('status', 1)->addAttributeToFilter('visibility', array('in' => array(2, 4)));
$tool = $this->getLayout()->createBlock('page/html_pager')->setLimit($this->getLayout()->createBlock('catalog/product_list_toolbar')->getLimit())->setCollection($prodCol);
$linkPrev = false;
$linkNext = false;
if ($tool->getCollection()->getSize()){
if ($tool->getLastPageNum() > 1){
if (!$tool->isFirstPage()) {
$linkPrev = true;
if($tool->getCurrentPage()==2){
$url = explode('?',$tool->getPreviousPageUrl());
$prevUrl = $url[0];
}
else $prevUrl = $tool->getPreviousPageUrl();
}
if (!$tool->isLastPage()){
$linkNext = true;
$nextUrl = $tool->getNextPageUrl();
}
}
}
if ($linkPrev) echo '<link rel="prev" href="'. $prevUrl .'" />';
if ($linkNext) echo '<link rel="next" href="'. $nextUrl .'" />';
}