I'm trying to implement an Ajax request to load more posts on click.
However I've got an error : Call to undefined function query_posts()
Here is my Ajax script :
$('#next-container').click(function() {
var IDs = [];
$(".element").each(function(){ IDs.push(this.id); });
$('#next-container').html('loading');
$.ajax({
url: 'wp-content/themes/freakyshape/inc/data.php',
type: 'POST',
data: {'post_ids[]': IDs },
success: function(data) {
$container.isotope( 'insert', $(data));
}
});
});
my data.php file to load post:
<?php
if (isset($_POST['post_ids'])) {
$ids = array();
$ids[] = $_POST['post_ids'];
$posts_per_page = 8;
global $wp_query;
query_posts(array('post_type' => array('post', 'portfolio'), 'post__not_in' => $ids, 'posts_per_page' => $posts_per_page));
while (have_posts()) : the_post();
?>
// I do some stuff echo;
<?php
endwhile;
wp_reset_query();
}
?>
and in my functions.php:
$admin_path = TEMPLATEPATH . "/inc/";
require_once ($admin_path . "data.php");
What do I need to make it work?
EDIT:
I try with the right way to do it but nothing works like this... I miss something... It's not easy to correctly understand blog instruction when you are not fluent in English...
function.php:
add_action('wp_ajax_load_post', 'load_post_callback');
add_action('wp_ajax_nopriv_load_post', 'load_post_callback');
wp_enqueue_script('script', get_template_directory_uri().'/js/load_post.js', array('jquery'), '1.0', 1 );
wp_localize_script('script', 'ajax_var', array('url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('ajax-nonce')));
load_post.php :
<?php
function load_post_callback() {
if (isset($_POST['post_ids'])) {
$nonce = $_POST['nonce'];
if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) ) {
die ( 'Interdit !');
}
$ids = array();
$ids[] = $_POST['post_ids'];
$posts_per_page = 8;
global $wp_query;
query_posts(array('post_type' => array('post', 'portfolio'), 'post__not_in' => $ids, 'posts_per_page' => $posts_per_page));
while (have_posts()) : the_post();
$post_type = get_post_type( $post->ID );
if ($post_type == 'post') {
$post_type = 'blog';
}
?>
<div class="element normal <?php echo $post_type; ?>" id="<?php echo the_id(); ?>">
<div class="element-container">
<img src="<?php echo wp_get_attachment_url( get_post_thumbnail_id()); ?>" class="thumbnail" />
<div class="element-back"></div>
<div class="element-description"><?php echo the_title(); ?></div>
<div class="element-category"><i class="icon"></i>   <?php echo $post_type; ?></div>
<a class="link" href="" title="<?php echo the_title(); ?>" onclick="gestionClic(compteur'id');">
<div class="more">more.</div>
</a>
</div>
</div>
<?php
endwhile;
wp_reset_query();
}
}
?>
load_post.js:
jQuery(document).ready(function() {
var url = ajax_var.url;
var nonce = ajax_var.nonce;
jQuery('#next-container').click(function() {
var IDs = [];
$(".element").each(function(){ IDs.push(this.id); });
console.log(IDs);
$('#next-container').html('loading');
$.ajax({
url: 'wp-content/themes/freakyshape/inc/load_post.php',
type: 'POST',
data: {'post_ids[]': IDs },//'post_ids='+IDs,
success: function($data) {
$container.isotope( 'insert', $data);
}
})
})
})
Using Ajax this way is not correct. For your code to work, you need to include wp-load.php and use some other workarounds. The web is full of this awful examples.
Otto, core contributor, explains the main reasons why we Don’t include wp-load, please.. And these are:
Why this is wrong
You don’t have the first clue where wp-load.php actually is. Both the plugin directory and the wp-content directory can be moved around
in the installation. ALL the WordPress files could be moved about in
this manner, are you going to search around for them?
You’ve instantly doubled the load on that server. WordPress and the PHP processing of it all now have to get loaded twice for every
page load. Once to produce the page, and then again to produce your
generated javascript.
You’re generating javascript on the fly. That’s simply crap for caching and speed and such.
The proper way is:
using wp_ajax_ hooks to run PHP code and return it to the JS file.
using wp_localize_script to pass PHP variables to the JS file.
One working example of mine at WordPress Answers. And lots of good examples from one of our mods and leading contributor to the Ajax tag.
Related
I am doing filtering posts using ajax.
I wish $ array was different for pages "Products" and "Faq"
If this is executed within an ajax request, is_page() won't be set. the page you're making the request from was a previous request. you need to set something on the originating page to pass with your ajax request to let it know it's for your special case page.
functions.php
function load_scripts() {
wp_enqueue_script( 'ajax', get_template_directory_uri() . '/vendor/jquery/main.js', array( 'jquery' ), NULL, true );
wp_localize_script( 'ajax', 'wp_ajax',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'is_page' => is_page( 420 ), // Whatever you want to pass. Add as many key pairs as needed.
)
);
}
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'];
if(isset($_POST['is_page']) && $_POST['is_page'] === 'faq'){
$cat__in = 10;
print_r( $_POST );
echo "FAQ";
} else{
$cat__in = 4;
print_r( $_POST );
echo "Products";
}
$args = array(
'post_type' => 'post',
'posts_per_page' => 50,
'category__in' => $cat__in,
);
if(isset($category)) {
$args['category__in'] = array($category);
}
$query = new WP_Query($args);
if($query->have_posts()) :
while($query->have_posts()) : $query->the_post();
the_title('<h2>', '</h2>');
the_content('<p>', '</p>');
endwhile;
endif;
wp_reset_postdata();
die();
}
faq.php
<div class="js-filter">
<?php
$args = array(
'post_type' => 'post',
'posts_per_page' => 100,
'child_of' => 10,
'exclude' => array(1),
);
$query = new WP_Query(array( 'cat' => 10 ));
if($query->have_posts()) :
while($query->have_posts()) : $query->the_post();
the_title('<h2>', '</h2>');
the_content('<p>', '</p>');
endwhile;
endif;
wp_reset_postdata(); ?>
</div>
<div class="categories">
<ul>
<?php
$cat_args = array(
'exclude' => array(1),
'child_of' => 10
);
?>
<?php
global $post;
$category = reset(get_the_category($post->ID));
$category_id = $category->cat_ID;
?>
<li class="js-filter-item">All</li>
<?php $categories = get_categories($cat_args); foreach($categories as $cat) : ?>
<li class="js-filter-item"><a data-category="<?= $cat->term_id; ?>" href="<?= get_category_link($cat->term_id); ?>"><?= $cat->name; ?></a></li>
<?php endforeach; ?>
</ul>
</div>
products.php
<div class="js-filter">
<?php
$args = array(
'post_type' => 'post',
'posts_per_page' => 100,
'child_of' => 6,
'exclude' => array(1,10),
);
$query = new WP_Query(array( 'cat' => 6 ));
if($query->have_posts()) :
while($query->have_posts()) : $query->the_post();
the_title('<h2>', '</h2>');
the_content('<p>', '</p>');
endwhile;
endif;
wp_reset_postdata(); ?>
</div>
<div class="categories">
<ul>
<?php
$cat_args = array(
'exclude' => array(1,10),
'child_of' => 6
);
?>
<?php
global $post;
$category = reset(get_the_category($post->ID));
$category_id = $category->cat_ID;
?>
<li class="js-filter-item">All</li>
<?php $categories = get_categories($cat_args); foreach($categories as $cat) : ?>
<li class="js-filter-item"><a data-category="<?= $cat->term_id; ?>" href="<?= get_category_link($cat->term_id); ?>"><?= $cat->name; ?></a></li>
<?php endforeach; ?>
</ul>
</div>
main.js
jQuery(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',
is_page: wp_ajax.is_page, // This param will be passed to your ajax function.
category: category,
pageslug: location.pathname.replace(/\//g,'')
},
type: 'post',
success: function(result) {
$('.js-filter').html(result);
},
error: function(result) {
console.warn(result);
}
});
});
});
do you have any idea how to solve it? After clicking on the "All" button, it displays posts from the "ID = 6" category
You can pass your parameter by using the localize script feature. Since the page isn't passed to your ajax function, you need to set your params in localize script, then pass to your ajax as part of the localized array.
function load_scripts() {
wp_enqueue_script( 'ajax', get_template_directory_uri() . '/vendor/jquery/main.js', array( 'jquery' ), NULL, true );
wp_localize_script( 'ajax', 'wp_ajax',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'is_page' => is_page( 420 ), // Whatever you want to pass. Add as many key pairs as needed.
)
);
}
add_action( 'wp_enqueue_scripts', 'load_scripts');
In the case above, is_page is either true or false, and will pass to your javascript via the localized script. So in the JS file, wp_ajax.is_page will be either true or false (you can view this by inspecting your js object on the page. It should be a 0 or a 1.
If you wanted to pass other objects, you can create as many items to your array and then pass to your js template.
Your AJAX:
jQuery(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',
is_page: wp_ajax.is_page, // This param will be passed to your ajax function.
category: category,
pageslug: location.pathname.replace(/\//g,'')
},
type: 'post',
success: function(result) {
$('.js-filter').html(result);
},
error: function(result) {
console.warn(result);
}
});
});
});
Then in your updated php ajax action.
function filter_ajax() {
$category = $_POST['category'];
// If it's page 420... then $_POST['is_page'] will equal a string 1.
if ( isset( $_POST['is_page'] ) && $_POST['is_page'] === '1' ) {
$cat__in = 10;
print_r( $_POST );
echo "FAQ";
} else {
$cat__in = 4;
print_r( $_POST );
echo "Products";
}
// .... rest of function
}
is_page() is not supposed to work in wp_ajax_ functions.
Check this answer: Why doesn't is_page(id) work in functions.php?
is_page() relies on a complete global $wp_query object. If you call it before the action template_redirect has been fired, it might be impossible to get that data.
Instead of using is_page(), you can pass the slug as ajax data array value.
To pass as slug, edit main.js to replace
data: { action: 'filter', category: category },
with
data: {
action: 'filter',
category: category,
pageslug: location.pathname.replace(/\//g,'')
},
Then, in functions.php in filter_ajax() function, replace
if (is_page('faq'))
with
if(isset($_POST['pageslug']) && $_POST['pageslug'] === 'faq')
I'm trying to create a load more button that loads more custom post types on click, however, I keep receiving a 400 (Bad Request) error. Here is the code i'm using.
// Header.php
<!doctype html>
<html <?php language_attributes(); class="no-js">
<head>
<!-- meta tags & links --->
<script type="text/javascript">
ajaxurl = <?php echo admin_url('admin-ajax.php'); ?>;
// HTML:
<div class="project">
<?php
$posts_array = array(
'post_type' => 'project',
'status' => 'publish',
'order' => 'ASC',
'posts_per_page' => -1,
'paged' => $paged
);
$posts = get_posts($posts_array);
$count = 0;
?>
<?php foreach ($posts as $post) : $count++; ?>
<div class="project">
<php echo the_title(); ?>
</div>
<?php endforeach; wp_reset_query(); ?>
</div>
<button id="more_posts">Load More</button>
// JavaScript:
$("#more_posts").on("click", function() {
// When btn is pressed.
$.ajax({
url: ajaxurl,
action: "more_post_ajax",
offset: page * ppp + 1,
ppp: ppp
}).success(function(posts) {
page++;
$(".projects").append(posts);
});
});
// Functions.php
function more_post_ajax(){
$offset = $_POST["offset"];
$ppp = $_POST["ppp"];
header("Content-Type: text/html");
$args = array(
'post_type' => 'project',
'status' => 'publish',
'posts_per_page' => $ppp,
'order' => 'ASC',
'offset' => $offset,
);
$loop = new WP_Query($args);
while ($loop->have_posts()) { $loop->the_post();
the_title();
}
exit;
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
There is a good amount here to fix.
Your Ajax is syntax is off a bit. Also, you can specify posts per page for the return with PHP, so you don't need to send that, you can keep your page attribute on the frontend.
$("#more_posts").on("click", function(e) {
$.ajax({
// use the ajax object url
url: ajax_object.ajax_url,
data: {
action: "more_post_ajax", // add your action to the data object
offset: page * 4 // page # x your default posts per page
},
success: function(data) {
// add the posts to the container and add to your page count
page++;
$('.projects').append(data);
},
error: function(data) {
// test to see what you get back on error
console.log(data);
}
});
});
For your initial PHP function, you should only specify the amount of posts you want to show at first. If you use -1 it will just show all posts at the start, which you don't want. You also don't need to use the paged parameter. You only need offsets.
<?php
$args = array(
'post_type' => 'project',
'status' => 'publish',
'order' => 'ASC',
'posts_per_page' => 4,
);
$posts = new WP_Query($args);
?>
<div class="projects">
<?php
while ($posts->have_posts()) {
$posts->the_post(); ?>
<div class="project">
<?php the_title(); ?>
</div>
<?php
wp_reset_postdata();
}; ?>
</div>
For your more posts function, you only need to specify an offset, and can add your additional posts right in that function.
function more_post_ajax(){
$offset = $_POST["offset"];
$args = array(
'post_type' => 'project',
'status' => 'publish',
'posts_per_page' => 4,
'order' => 'ASC',
'offset' => $offset,
);
$post = new WP_Query($args);
while ($post->have_posts()) { $post->the_post();
<div class="project">the_title();</div>
}
wp_reset_postdata();
die(); // use die instead of exit
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
I have not tested this, but this should get you closer to a working set.
Just in case anyone is looking at this in the future and aren't sure on why they can't make it work theres a couple of things that need changing in the above code for starters in the js you need to define the variable page before the on click function...
var page = 1;
$("#more_posts").on("click", function(e) {
$.ajax({
// use the ajax object url
url: ajax_object.ajax_url,
data: {
action: "more_post_ajax", // add your action to the data object
offset: page * 4 // page # x your default posts per page
},
success: function(data) {
// add the posts to the container and add to your page count
page++;
$('.projects').append(data);
},
error: function(data) {
// test to see what you get back on error
console.log(data);
}
});
});
This code appends the data to the admin-ajax url which means you have to use $_GET not $_POST to retrieve the offset variable in your php function:
$offset = $_GET["offset"];
I'm trying to load post with ajax using a variable to get posts by year. I've found this great tutorial https://www.creare.co.uk/blog/simple-wp_query-ajax and I'm trying to modify it to my needs but I have 0 experience with Ajax and not so much with jquery...
this is my modified code but the year is not passed and I don't know how to do it, I appreciate any help
js
//If input is changed, load posts
$('#genre-filter input').live('change', function(){
genre_get_posts(); //Load Posts
});
//Find Selected Genres
function getSelectedGenres()
{
var genres = [];
$("#genre-filter div").click(function() {
var genres = $(this).attr('value');
console.log(genres);
});
return genres;
}
//Main ajax function
function genre_get_posts(paged)
{
var ajax_url = ajax_genre_params.ajax_url;
$.ajax({
type: 'GET',
url: ajax_url,
data: {
action: 'genre_filter',
genres: getSelectedGenres,
},
beforeSend: function ()
{
//Show loader here
},
success: function(data)
{
//Hide loader here
$('#genre-results').html(data);
},
error: function()
{
$("#genre-results").html('<p>There has been an error</p>');
}
});
}
template
<section id="primary" class="content-area">
<div id="content" class="site-content" role="main">
<?php
if ( have_posts() ):
while ( have_posts() ): the_post();
get_template_part( 'content' );
endwhile;
endif;
?>
<div class="entry-content">
<div id="genre-filter">
<div id="2018" value="2018" name="filter_genre[]">2018</div>
<div id="2017" value="2017" name="filter_genre[]">2017</div>
</div>
<div id="genre-results"></div>
</div>
</div>
functions.php
function ajax_genre_filter() {
$query_data = $_GET;
$genre_terms = ( $query_data[ 'genres' ] ) ? explode( ',', $query_data[ 'genres' ] ) : false;
$book_args = array(
'post_type' => 'book',
'posts_per_page' => 2,
'year' => $genre_terms,
);
$book_loop = new WP_Query( $book_args );
if ( $book_loop->have_posts() ):
while ( $book_loop->have_posts() ): $book_loop->the_post();
get_template_part( 'content' );
endwhile;
echo $query_data;
else :
get_template_part( 'content-none' );
endif;
wp_reset_postdata();
die();
}
Your first issue is variable scoping in getSelectedGenres. I would imaging you're always getting an empty array due to the 2nd var in your event handler. Try the modified version below.
function getSelectedGenres()
{
var genres = [];
$("#genre-filter div").click(function() {
var g = $(this).attr('value');
genres.push(g);
console.log(g);
});
return genres;
}
Additionally, it looks like ajax_genre_filter reads the year from the genres query string genres based on the mapping 'year' => $genre_terms so try including the selected year in your function getSelectedGenres.
I am trying to create a live search using ajax and jquery on my custom WordPress theme. If i use .click() function it is showing desired output but when using .keyup or on('input',function(){}) it display nothing.
Jquery code
var searchRequest = null;
var minlength = 3;
$(".search-submit").on('input',function(e){
e.preventDefault();
var st=$(".search-field").val();
if (st.length >= minlength )
{
if (searchRequest != null)
searchRequest.abort();
searchRequest=$.ajax({
type:"POST",
url: "./wp-admin/admin-ajax.php",
data: {
action:'wpa56343_search',
search_string:st
},
success:function(data){
$('.srch-result').append(data);
}
});
}
});
PHP code of function.php
add_action('wp_ajax_nopriv_wpa56343_search', 'wpa56343_search');
add_action('wp_ajax_wpa56343_search', 'wpa56343_search');
function wpa56343_search()
{
global $wp_query;
$search = $_POST['search_string'];
$args = array(
's' => $search,
'posts_per_page' => 5
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) :
while ( $query->have_posts() ) :
$query->the_post();
get_template_part( 'template-parts/ajax-search-format', get_post_format() );
endwhile;
endif;
wp_reset_postdata();
}
Please show your html structure too.
I think you are trying to trigger with the wrong element.
Maybe $(".search-submit") is not a input field.
Try:
$(".search-field").on('input',function(e){
//** YOUR CODE **/
});
I am currently working in wordpress and I have a link that is supposed to play a wav file depending on the title of the post. So if the post title is 'one' then it should play one.wav from the uploads folder. However, the sound file on every post only plays the most current posts title. So if I added a post called two and then a post called one, both posts will play one.wav.
Here's the code:
HTML
<span id="dummy"></span>
<a class="playSound" onclick="playSound();" href="#">
<i class="fa fa-volume-up"></i>
</a>
JQuery
function playSound() {
$.ajax({
url: 'sound.php',
data: "getSound",
type: "GET",
datatype: "html",
success: function(data) {
document.getElementById("dummy").innerHTML= "<embed src=\""+data+"\" hidden=\"true\" autostart=\"true\"loop=\"false\" />";
}
});
}
and the PHP
<?php
require('./wp-blog-header.php');
if(isset($_GET['getSound'])) {
$file='wp-content/uploads/2015/wav/' . get_the_title() . '.wav';
echo $file;
}
?>
I assume get_the_title() is the proper call but at this point I am not so sure. I have tried all the other call functions but still no luck. I assume at this point is has to do with the loading of the page and storing the initial posts title but i am just lost at this point.
<?php
$sound_query = new WP_Query();
if ($sound_query->have_posts()):
while ($sound_query->have_posts()):
$sound_query->the_post();
?>
<script>
function playSound() {
document.getElementById("dummy").innerHTML= "<embed src='wp-content/uploads/2015/wav/<?php echo get_the_title() ?>.wav' />";
}
</script>
<?php
endwhile;
endif;
wp_reset_postdata();
?>
Change your sound.php file code like
<?php
require('./wp-blog-header.php');
global $post;
setup_postdata( $post );
if(isset($_GET['getSound'])) {
$file='wp-content/uploads/2015/wav/' . get_the_title( get_the_ID() ) . '.wav';
echo $file;
}
?>
You can simply get ride of your second php code and just use javascript:
function playSound() {
document.getElementById("dummy").innerHTML= "<embed src='wp-content/uploads/2015/wav/<?php echo get_the_title( get_the_ID() ) ?>.wav' />";
}
Everything is disjointed. The JS file doesn't know what post you are trying to target, and hence the sound.php file doesn't know either.
Pass the post ID to the JS file and then pass it to the sound.php file, then extract the post from that.
Also, try not using the post title for such things, use the ID as the post title and post name can be changed.
Example:
HTML
<a class="playSound" onclick="playSound(<?php echo $post->ID; ?>);" href="#">
<i class="fa fa-volume-up"></i>
</a>
JS
function playSound(postID) {
$.ajax({
url: 'sound.php',
data: data: {"postID": postID
type: "GET",
datatype: "html",
success: function(data) {
//Function here
})
}
PHP
if(isset($_GET['postID'])) {
$file='wp-content/uploads/2015/wav/' . $_GET['postID'] . '.wav';
echo $file;
}
Or something similar to that anyway.