I have inherited a project using a child theme based on the Avada theme. The previous developer has created a plugin to add custom elements to the Avada fusion builder. One of those elements, the Community Filter element, loops through a CPT named ‘custom_people’ and asks that you specify one or more taxonomy terms to be displayed within that loop on the front end. This element also functions with AJAX, where you can filter the results using the filter form, that sits above the cards, or you can click a load more button below the cards that will load the next 8 (or whatever number you specify) cards.
Function to loop ‘custom_people’ CPT
private function getOpportunities($project_category = ''){
$terms = get_the_terms( get_the_ID(), $this->taxonomy_name );
if ($terms) {
$project_category = array();
foreach($terms as $term) {
$project_category[] = $term->slug;
}
}
$args= null;
$args = array(
'posts_per_page' => $this->posts_per_page,
'post_type' => 'custom_people',
'suppress_filters' => false,
'orderby' => 'meta_value',
'meta_key' => 'last_name',
'order' => 'ASC',
'tax_query' => array(
array(
'taxonomy' => $this->taxonomy_name,
'field' => 'slug',
'terms' => $project_category
)
)
);
$all_posts = new WP_Query( $args );
// $ajax_posts = $all_posts->posts;
//
// $post = get_posts($args);
wp_reset_postdata();
return $all_posts;
}
I tweaked the function above by adding (placed at the top)
$terms = get_the_terms( get_the_ID(), $this->taxonomy_name );
if ($terms) {
$project_category = array();
foreach($terms as $term) {
$project_category[] = $term->slug;
}
}
And then added these two lines
$committee_category_new = array();
$committee_category_new = explode(',', $committee_category);
So that I could list the terms as an array in the tax_query parameter. This enabled the page I’ve assigned to display the two terms to work as expected. The screen shot below is the page to which I’m referring. It’s successfully looping through and display posts from two different taxonomy terms.
However, if I click the ‘load more’ button that’s underneath the second row of cards in the photo, all cards disappear. So this leads me to believe that there is something that I’ve left out in my AJAX function, now that I’ve added the code snippets mentioned above.
AJAX function is still shown below.
So to sum up the issue, when I want to display cards from only one taxonomy term, the cards load as expected for that term, and the AJAX also works as expected. However, if I assign two terms for display, they will load properly on page load, but AJAX inputs will fail. Please note that I’ve also tested showing all posts from the two terms on page load, and they all display as expected. So this definitely seems like a piece that I’m missing from within the AJAX function.
(From original post: All is working fine if only one term is selected, but if two terms are selected, the filter and load more buttons, when clicked, produce no results. In other words, if you click the load more button, or perform a filter submission, no additional results get populated, and all currently displayed posts disappear.)
AJAX function
public function community_ajax(){
$result['type'] = "success";
// $result['data'] = 'hello World!';
$result['data'] = $_REQUEST['value'];
$result['category'] = $_REQUEST['category'];
if(isset($_REQUEST['date'])){
$result['date'] = $_REQUEST['date'];
}else{
$result['date'] = 0;
}
$result['location'] = $_REQUEST['location'];
$result['committee'] = '';
$select_bio = null;
if(isset($_REQUEST['select_bio'])){
$select_bio = $_REQUEST['select_bio'];
}
$committee_category = null;
if(isset($_REQUEST['committee_category'])){
$committee_category = $_REQUEST['committee_category'];
$_REQUEST['category'] = $_REQUEST['committee_category'];
$result['category'] = $_REQUEST['committee_category'];
}
$show_contact = null;
if(isset($_REQUEST['show_contact'])){
$show_contact = $_REQUEST['show_contact'];
}
$show_url = null;
if(isset($_REQUEST['show_url'])){
$show_url = $_REQUEST['show_url'];
}
$lazy_num = null;
if(isset($_REQUEST['lazy_num'])){
$lazy_num = intval($_REQUEST['lazy_num']);
}
$show_student_info = null;
if(isset($_REQUEST['show_student_info'])){
$show_student_info = $_REQUEST['show_student_info'];
}
$ajax_posts = array();
$args = array(
'post_type' => $this->post_name,
'posts_per_page' => !empty($lazy_num) ? $lazy_num : $this->posts_per_page,
'orderby' => 'meta_value',
'meta_key' => 'last_name',
'order' => 'ASC',
'suppress_filters' => false,
);
if($_REQUEST['date'] != "0" && $_REQUEST['date'] != 0 ){
$date = strtotime($_REQUEST['date']);
$args['date_query'] = array(
array(
'year' => date("Y", $date),
'month' => date("n", $date),
)
);
}
if(($_REQUEST['category'] ) && ($_REQUEST['location'] != "0" && $_REQUEST['location'] != 0)){
$args['tax_query'] = array(
'relation' => 'AND',
array(
'taxonomy' => $this->taxonomy_name,
'field' => 'slug',
'terms' => array( $_REQUEST['category'] ),
),
array(
'taxonomy' => $this->location_name,
'field' => 'term_id',
'terms' => array( (int)$_REQUEST['location'] ),
)
);
}else{
if($_REQUEST['category']){
$args['tax_query'] = array(
array(
'taxonomy' => $this->taxonomy_name,
'field' => 'slug',
'terms' => array( $_REQUEST['category'] ),
)
);
}
if($_REQUEST['location'] != "0" && $_REQUEST['location'] != 0){
$args['tax_query'] = array(
array(
'taxonomy' => $this->location_name,
'field' => 'term_id',
'terms' => array( (int)$_REQUEST['location'] ),
)
);
}
}
if($_REQUEST['category'] != "0" && $_REQUEST['category'] != 0){
$result['committee'] = $this->excerpt_chunk($_REQUEST['category']);
$result['committee_default'] = false;
}else{
$result['committee_default'] = true;
}
if($_REQUEST['value']){
$args['s'] = $_REQUEST['value'];
}
if($_REQUEST['offset']){
$args['paged'] = $_REQUEST['offset'];
$result['offset'] = $_REQUEST['offset'];
}
$ajax_posts = get_posts( $args );
$all_posts = new WP_Query( $args );
// $ajax_posts = $all_posts->posts;
$count = count($ajax_posts);
// for ($i=0; $i < $count; $i++) {
// # code...
// // $ajax_posts[$i]->thumbnail = get_the_post_thumbnail_url( $ajax_posts[$i]->ID, 'medium' );
// $ajax_posts[$i]->category = get_the_terms( $ajax_posts[$i]->ID, 'project_category' )[0]->name;
// $ajax_posts[$i]->location = get_the_terms( $ajax_posts[$i]->ID, 'project_location' )[0]->name;
// $ajax_posts[$i]->link = get_permalink( $ajax_posts[$i] );
// }
wp_reset_postdata();
$result['query'] = $args;
$result['posts'] = array();
$result['wp_query'] = $all_posts;
$args = array(
"bio" => $select_bio,
"show_tags" => $show_tags,
"show_url" => $show_url,
"committee_category" => $committee_category,
"show_contact" => $show_contact,
"show_student_info" => $show_student_info
);
foreach ($ajax_posts as $post) {
# code...
// echo json_encode($post);
// array_push($result['posts'], $post);
array_push($result['posts'], $this->instanceFeatureProject($post, $args));
}
$result['posts_json'] = $ajax_posts;
// Check if action was fired via Ajax call. If yes, JS code will be triggered, else the user is redirected to the post page
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$result = json_encode($result);
echo $result;
}
else {
header("Location: ".$_SERVER["HTTP_REFERER"]);
}
// don't forget to end your scripts with a die() function - very important
die();
}
JS
"use strict";
jQuery(document).ready(function () {
var search_btn = jQuery(".communities_filter_element .text_filter .icon i");
var text_input = jQuery(".communities_filter_element .text_filter .text_input input");
var select_box_category = jQuery("#committee_cat");
var select_box_location = jQuery(".communities_filter_element .project_filter .custom-select.location select");
var select_box_date = jQuery(".communities_filter_element .project_filter .custom-select.date select");
var view = jQuery(".communities_filter_element .projects");
var load_more_btn = jQuery(".communities_filter_element .load-more");
var page_offset = 1;
var ajax_action = 'community_filter_ajax';
var except_location = jQuery('.communities_filter_element .committee-excerpt');
var default_except_location = jQuery('.communities_filter_element .committee-excerpt-default');
var hidden_fields = jQuery('.communities_filter_element .hidden_inputs');
initSelect();
search_btn.click(function (e) {
applyFilter(e);
});
jQuery(".select-items > div").click(function (e) {
applyFilter(e);
});
load_more_btn.click(function (e) {
loadMore(e);
jQuery(".communities_filter_element").addClass('more_loaded');
});
hideLoadMore();
jQuery('.project_filter > div.text_filter > div.text_input > input[type=textfield]').keypress(function (e) {
if (e.which == 13) {
applyFilter(e);
return false; //<---- Add this line
}
});
function insertCommitteeExcerpt(html, default_excerpt) {
except_location.empty();
if (default_excerpt) {
except_location.hide();
default_except_location.show();
} else {
except_location.append(html);
except_location.show();
default_except_location.hide();
}
}
function applyFilter(e) {
var loadingDiv =
'<div class="loading-screen" style="position: absolute; top: 0px; left: 0px; height: 300px; width: 100%; align-items: center; justify-content: center;">' +
'<h3 style="padding: .5em 1em; background-color: #fff; border-radius: 3px;">Loading...</h3>' +
'</div>';
var post_data = {
action: ajax_action,
value: text_input.val(),
category: select_box_category.val(),
date: select_box_date.children("option:selected").val(),
location: select_box_location.children("option:selected").val(),
committee_category: hidden_fields.children("#committee_category").val(),
show_contact: hidden_fields.children("#show_contact").val(),
show_tags: hidden_fields.children("#show_tags").val(),
show_url: hidden_fields.children("#show_url").val(),
lazy_num : hidden_fields.children("#lazy_num").val(),
show_student_info: hidden_fields.children("#show_student_info").val(),
select_bio : hidden_fields.children("#select_bio").val()
};
console.log(post_data);
e.preventDefault();
jQuery.ajax({
type: "post",
dataType: "json",
url: document.location.origin + '/wp-admin/admin-ajax.php',
data: post_data,
beforeSend: function() {
jQuery(loadingDiv).insertAfter('.project_filter').hide().fadeIn().css('display', 'flex');
jQuery('.projects').css('opacity', '.25');
},
complete: function(){
jQuery('.loading-screen').fadeOut(function() {
jQuery(this).remove();
});
jQuery('.projects').css('opacity', '1');
},
success: function (response) {
if (response.type == "success") {
console.log(response);
removeAllPosts();
populatePosts(response.posts);
insertCommitteeExcerpt(response.committee, response.committee_default);
hidden_fields.children("#max_num_pages").val(response.wp_query.max_num_pages);
showLoadMore();
hideLoadMore();
}
}
});
}
function loadMore(e) {
e.preventDefault();
page_offset++;
var loadingDiv =
'<div class="loading-screen" style="align-items: center; justify-content: center; display: flex;">' +
'<h3 style="padding: .5em 1em; background-color: #fff; border-radius: 3px;">Loading...</h3>' +
'</div>';
var data = {
action: ajax_action,
value: text_input.val(),
category: select_box_category.children("option:selected").val(),
date: select_box_date.children("option:selected").val(),
location: select_box_location.children("option:selected").val(),
offset: page_offset,
committee_category: hidden_fields.children("#committee_category").val(),
show_contact: hidden_fields.children("#show_contact").val(),
show_tags: hidden_fields.children("#show_tags").val(),
show_url: hidden_fields.children("#show_url").val(),
lazy_num : hidden_fields.children("#lazy_num").val(),
show_student_info: hidden_fields.children("#show_student_info").val(),
select_bio : hidden_fields.children("#select_bio").val()
};
console.log(data);
jQuery.ajax({
type: "post",
dataType: "json",
url: document.location.origin + '/wp-admin/admin-ajax.php',
data: data,
beforeSend: function() {
jQuery(loadingDiv).insertAfter('.projects').hide().fadeIn().css('display', 'flex');
jQuery('.projects').css('opacity', '.25');
},
complete: function(){
jQuery('.loading-screen').fadeOut(function() {
jQuery(this).remove();
});
jQuery('.projects').css('opacity', '1');
},
success: function (response) {
if (response.type == "success") {
console.log(response);
populatePosts(response.posts);
hidden_fields.children("#max_num_pages").val(response.wp_query.max_num_pages);
hideLoadMore();
} else {
alert("An error has occured.");
}
}
});
}
function hideLoadMore() {
console.log('hide pageoffset', hidden_fields.children("#max_num_pages").val() <= page_offset);
if (hidden_fields.children("#max_num_pages").val() <= page_offset) {
jQuery('.load-more').addClass('hidden');
jQuery(".communities_filter_element").addClass('more_loaded');
}
}
function showLoadMore() {
console.log('pageoffset', page_offset);
if (hidden_fields.children("#max_num_pages").val() > page_offset) {
jQuery('.load-more').removeClass('hidden');
}
}
function populatePosts(posts) {
var count = posts.length;
for (var i = 0; i < count; i++) {
view.append(posts[i]);
}
}
function removeAllPosts() {
view.empty();
page_offset = 1;
}
function initSelect() {
var x, i, j, selElmnt, a, b, c;
/* Look for any elements with the class "custom-select": */
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
selElmnt = x[i].getElementsByTagName("select")[0];
/* For each element, create a new DIV that will act as the selected item: */
a = document.createElement("DIV");
a.setAttribute("class", "select-selected");
a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
x[i].appendChild(a);
/* For each element, create a new DIV that will contain the option list: */
b = document.createElement("DIV");
b.setAttribute("class", "select-items select-hide");
for (j = 1; j < selElmnt.length; j++) {
/* For each option in the original select element,
create a new DIV that will act as an option item: */
c = document.createElement("DIV");
c.innerHTML = selElmnt.options[j].innerHTML;
c.addEventListener("click", function (e) {
/* When an item is clicked, update the original select box,
and the selected item: */
var y, i, k, s, h;
s = this.parentNode.parentNode.getElementsByTagName("select")[0];
h = this.parentNode.previousSibling;
for (i = 0; i < s.length; i++) {
if (s.options[i].innerHTML == this.innerHTML) {
s.selectedIndex = i;
h.innerHTML = this.innerHTML;
y = this.parentNode.getElementsByClassName("same-as-selected");
for (k = 0; k < y.length; k++) {
y[k].removeAttribute("class");
}
this.setAttribute("class", "same-as-selected");
break;
}
}
h.click();
});
b.appendChild(c);
}
x[i].appendChild(b);
a.addEventListener("click", function (e) {
/* When the select box is clicked, close any other select boxes,
and open/close the current select box: */
e.stopPropagation();
closeAllSelect(this);
this.nextSibling.classList.toggle("select-hide");
this.classList.toggle("select-arrow-active");
});
}
function closeAllSelect(elmnt) {
/* A function that will close all select boxes in the document,
except the current select box: */
var x,
y,
i,
arrNo = [];
x = document.getElementsByClassName("select-items");
y = document.getElementsByClassName("select-selected");
for (i = 0; i < y.length; i++) {
if (elmnt == y[i]) {
arrNo.push(i);
} else {
y[i].classList.remove("select-arrow-active");
}
}
for (i = 0; i < x.length; i++) {
if (arrNo.indexOf(i)) {
x[i].classList.add("select-hide");
}
}
}
/* If the user clicks anywhere outside the select box,
then close all select boxes: */
document.addEventListener("click", closeAllSelect);
jQuery(".communities_filter_element .project_filter .second_row > div.clear-filter").on("click", function () {
window.location.reload(false);
});
}
});
I’m wondering if someone can show me how to ensure AJAX functions as expected when two terms are chosen for the loop.
Please note, I realize this is a lot of code, so it may be easier if I share the dev site as it’s currently being developed. That way you can see how one loop is working, versus another that’s not.
Thanks.