WP_Query with ajax handler returns the same posts - ajax

I have a problem that is getting me bald atm. I have a ajax call that handles a loop that handles some querys and returns posts for me.
So far so good, but the first time the user sees the page we should load 10 posts, and then we want to click a button to request 5 more.
So far so good.
But when we request the 5 more posts we get the 5 first posts again.
My batchloop
<?php
// Our include
define('WP_USE_THEMES', false);
require_once('../../../wp-load.php');
// Our variables
$posts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;
$category = (isset($_GET['category_name'])) ? $_GET['category_name'] : 0;
var_dump($posts);
$args = array(
'posts_per_page' => $posts,
'category_name' => $category,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'paged' => $page
);
query_posts($args);
// $query = new WP_query($args);
// our loop
if (have_posts()) {
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; query_posts($args);
while (have_posts()){
the_post();
get_template_part( 'thumbs', get_post_format() );
}
}
// unset($page, $posts, $category);
// wp_reset_postdata();
wp_reset_query();
?>
Does anybody sees what im doing wrong?
EDIT:
batch handler
function _batchhandler() {
var getamount = localStorage.getItem('amount');
console.log('amount of posts to retrive ' + JSON.parse(getamount));
// Ajax call
$.ajax({
type: 'GET',
data: {
posts: getamount,
page: page,
category: 'work'
},
dataType: 'html',
url: 'http://dev.xxx.se/wp-content/themes/xxx/batch.php',
beforeSend: function() {
_setHeader;
if( page != 1 ) {
console.log('Loading');
// Show the preloader
$('body').prepend('<div class="preloader"><span class="rotate"></span></div>');
}
// If we reach the end we hide the show more button
if( page >= total ) {
$('.load').hide();
}
},
success: function(data) {
console.log(page);
var scroll = ($('.thumb').height() * posts);
// If thumbs exist append them
if( data.length ) {
// Append the data
$('#batch').append(data);
// Remove the crappy width and height attrs from the image * Generated by WP *
$('img').removeAttr('height').removeAttr('width');
// Animate each new object in a nice way
(function _showitem() {
$('#batch .thumb:hidden:first').addClass('show', 80, _showitem);
// On the last request do load any more
loading = false;
})();
// Remove the preloader
$('.preloader').fadeOut(200, function() {
$('.preloader').remove();
});
}
// return false;
},
complete: function() {
// Delete storage
localStorage.clear();
// Update the scroller to match the updated content length
if (scroller)
setTimeout("scroller.refresh()", 300);
// Initalize the load more button
_clickhandler();
},
error: function() {
console.log('No page found');
}
});
}
and my load more button function
$('.load').on('click', function(event) {
event.preventDefault();
// Delete storage
localStorage.clear();
if(!loading) {
loading = true;
// Increase our pagenumber per click
page++;
count++;
// Remove preloader
$('.preloader').remove();
setTimeout(function() {
$('#batch').css({
'-webkit-transform' : 'translateY(-' + ($('#batch li').outerHeight() * count) + 'px)'
});
}, 30);
// Clear storage and set a new
localStorage.setItem('amount', JSON.stringify(amount.medium));
var getamount = localStorage.getItem('amount');
// Send the request to the handler
_batchhandler(page);
}
});
Everything seems fine, the first 10 (1-10) posts loads as the should, but the first time "load more" is clicked we get the next 5 results but the results are posts that loaded the first time (5-10). If we click the "load more" again, we get the correct result

I don't think you have defined a start value for page, set it to 1 at the start of your script so when it increments on click it goes to page 2. Otherwise it'll just get the first page.

Related

How add the Woocommerce notices(without reload) when using add to cart with ajax?

I try to make the add to cart buttons and notices on the productpages(and everywhere else) work with ajax. But the notices (e.g. You cannot add that amount to the cart - we have X in stock and you already have Y in your cart.) don't work.
How do I make it work?
This is what I have right now:
JS for AJAX Add to Cart handling
/**
* JS for AJAX Add to Cart handling
*/
function ace_product_page_ajax_add_to_cart_js() {
?><script type="text/javascript" charset="UTF-8">
jQuery(function($) {
$('form.cart').on('submit', function(e) {
e.preventDefault();
var form = $(this);
form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });
var formData = new FormData(form.context);
formData.append('add-to-cart', form.find('[name=add-to-cart]').val() );
// Ajax action.
$.ajax({
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'ace_add_to_cart' ),
data: formData,
type: 'POST',
processData: false,
contentType: false,
complete: function( response ) {
response = response.responseJSON;
if ( ! response ) {
return;
}
if ( response.error && response.product_url ) {
window.location = response.product_url;
return;
}
// Redirect to cart option
if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
window.location = wc_add_to_cart_params.cart_url;
return;
}
var $thisbutton = form.find('.single_add_to_cart_button'); //
var $thisbutton = null; // don't want the 'View cart' button
// Trigger event so themes can refresh other areas.
$( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );
// Remove existing notices
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
// Add new notices
form.closest('.product').before(response.fragments.notices_html)
form.unblock();
}
});
});
});
</script><?php
}
add_action( 'wp_footer', 'ace_product_page_ajax_add_to_cart_js' );
Add to cart handler:
/**
* Add to cart handler
*/
function ace_ajax_add_to_cart_handler() {
WC_Form_Handler::add_to_cart_action();
WC_AJAX::get_refreshed_fragments();
}
add_action( 'wc_ajax_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
// Remove WC Core add to cart handler to prevent double-add
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );
Add fragments for notices:
/**
* Add fragments for notices
*/
function ace_ajax_add_to_cart_add_fragments( $fragments ) {
$all_notices = WC()->session->get( 'wc_notices', array() );
$notice_types = apply_filters( 'woocommerce_notice_types', array( 'error', 'success', 'notice' ) );
ob_start();
foreach ( $notice_types as $notice_type ) {
if ( wc_notice_count( $notice_type ) > 0 ) {
wc_get_template( "notices/{$notice_type}.php", array(
'messages' => array_filter( $all_notices[ $notice_type ] ),
) );
}
}
$fragments['notices_html'] = ob_get_clean();
wc_clear_notices();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'ace_ajax_add_to_cart_add_fragments' );
Try replacing in last snippet 'messages' => array_filter( ... with 'notices' => array_filter( ... and it should work.

Post 500 (Internal Server error) ajax in codeigniter

I have a problem to sending data with ajax, when i click button save to sending data to database. but when i push F12 the error show
POST http://[::1]/sys-web/admlogin/manufacture/addmanufacture 500 (Internal Server Error)
send # http://[::1]/sys-web/assets/js/jquery-2.1.4.min.js:4
ajax # http://[::1]/sys-web/assets/js/jquery-2.1.4.min.js:4
save # http://[::1]/sys-web/admlogin/manufacture:374
onclick # http://[::1]/sys-web/admlogin/manufacture:507
CI Controller
public function AddManufacture()
{
$data = array(
'manufacturing_name' => $this->input->post('manufacturing_name'),
'address' => $this->input->post('address'),
'email' => $this->input->post('email'),
'telephone' => $this->input->post('telephone'),
'join_date' => $this->input->post('join_date')
);
$insert = $this->m_manufacture->save($data);
echo json_encode(array("status" => TRUE));
}
CI Model :
function save($data)
{
$sql = $this->db->insert($this->table, $data);
return $sql;
}
CI View :
function save()
save_method = 'add';
{
$('#btnSave').text('saving...'); //change button text
$('#btnSave').attr('disabled',true); //set button disable
var url;
if(save_method == 'add') {
url = "<?php echo site_url('admlogin/manufacture/addmanufacture')?>";
} else {
url = "<?php echo site_url('admlogin/manufacture/editmanufacture')?>";
}
// ajax adding data to database
var formData = new FormData($('#form')[0]);
$.ajax({
url : url,
type: "POST",
data: formData,
contentType: false,
processData: false,
dataType: "JSON",
success: function(data)
{
if(data.status) //if success close modal and reload ajax table
{
$('#modal_form').modal('hide');
reload_table();
}
else
{
for (var i = 0; i < data.inputerror.length; i++)
{
$('[name="'+data.inputerror[i]+'"]').parent().parent().addClass('has-error'); //select parent twice to select div form-group class and add has-error class
$('[name="'+data.inputerror[i]+'"]').next().text(data.error_string[i]); //select span help-block class set text error string
}
}
$('#btnSave').text('save'); //change button text
$('#btnSave').attr('disabled',false); //set button enable
},
error: function (jqXHR, textStatus, errorThrown)
{
alert('Error adding / update data');
$('#btnSave').text('save'); //change button text
$('#btnSave').attr('disabled',false); //set button enable
}
});
}

ember model find query with params doesn't display on pagination

2I have an Ember app which connects to an api from where it gets articles. I make use of pagination to get 10 articles per request. This works. But now I wanted to add sorting to the request. I implemented this by using the extra parameter in the store.find.
However, for some reason if I use the 'return this.store.find('article', params);' instead of 'return this.store.find('article');' new articles (still requested and added correctly to the store!) in the getMore function are not beiing displayed or rendered. But when i remove the params parameter from store.find in model, it does work. What could be the case here?
templates/articles.hbs
<script type="text/x-handlebars" data-template-name="articles">
{{#each itemController="article"}}
<div class="item">
//...
</div>
{{/each}}
</script>
routes/articles.js
import Ember from 'ember';
export default Ember.Route.extend(Ember.UserApp.ProtectedRouteMixin, {
model: function(params) {
var params2 = {page: 1, per_page: 10, sort: params.sort};
return this.store.find('article', params2);
},
setupController: function(controller, model) {
controller.set('content', model);
},
actions:{
//...
},
getMore: function() {
// don't load new data if we already are
//if (this.get('loadingMore')) return;
//this.set('loadingMore', true);
var meta = this.store.metadataFor("article");
if (meta.hasmore) {
var controller = this.get('controller'),
nextPage = controller.get('page') + 1,
perPage = controller.get('perPage'),
sorting = controller.get('sort'),
items;
var params = {page: nextPage, per_page: perPage, sort: sorting};
this.store.findQuery('article', params).then(function (articles) {
controller.set('page', controller.get('page') + 1);
//this.set('loadingMore', false);
});
}
else{
$('#pagination_spinner').hide();
}
},
queryParamsDidChange: function() {
this.refresh();
}
}
});
controllers/articles.js
import Ember from 'ember';
var ArticlesController = Ember.ArrayController.extend({
itemController: 'article',
queryParams: ['sort'],
sort: 'rating',
page: 1,
perPage: 10
});
export default ArticlesController;
views/articles.js
import Ember from 'ember';
export default Ember.View.extend({
didInsertElement: function(){
//this.scheduleMasonry();
this.applyMasonry();
// we want to make sure 'this' inside `didScroll` refers
// to the IndexView, so we use jquery's `proxy` method to bind it
//this.applyMasonry();
$(window).on('scroll', $.proxy(this.didScroll, this));
},
willDestroyElement: function(){
this.destroyMasonry();
// have to use the same argument to `off` that we did to `on`
$(window).off('scroll', $.proxy(this.didScroll, this));
},
// this is called every time we scroll
didScroll: function(){
if (this.isScrolledToBottom()) {
$('#pagination_spinner').addClass('active');
this.get('controller').send('getMore');
}
},
scheduleMasonry: (function(){
Ember.run.scheduleOnce('afterRender', this, this.applyMasonry);
}).observes('controller.model.#each'), //TODO check
applyMasonry: function(){
$('#pagination_spinner').removeClass('active');
var $galleryContainer = $('#galleryContainer');
$galleryContainer.imagesLoaded(function() {
// check if masonry is initialized
var msnry = $galleryContainer.data('masonry');
if ( msnry ) {
msnry.reloadItems();
// disable transition
var transitionDuration = msnry.options.transitionDuration;
msnry.options.transitionDuration = 0;
msnry.layout();
// reset transition
msnry.options.transitionDuration = transitionDuration;
} else {
// init masonry
$galleryContainer.masonry({
itemSelector: '.item',
columnWidth: 0,
"isFitWidth": true
});
}
});
},
destroyMasonry: function(){
$('#galleryContainer').masonry('destroy');
},
// we check if we are at the bottom of the page
isScrolledToBottom: function(){
var distanceToViewportTop = (
$(document).height() - $(window).height());
var viewPortTop = $(document).scrollTop();
if (viewPortTop === 0) {
// if we are at the top of the page, don't do
// the infinite scroll thing
return false;
}
return (viewPortTop - distanceToViewportTop === 0);
}
});
nothing smart coming to my mind, but maybe it's that...
You've got the line:
if (meta.hasmore) {
in your getMore() function. Is this the case that you've got this meta field in one response and forgot in the other?

AJAX loop for WordPress (posts from different categories)

I try to implement AJAX posts loop for WordPress from Tuts+
I want this loop to show under comments form in single post page in three columns (each for another category)
In single.php I have divs (numbers comes from category):
<div class="news_posts-6"></div>
<div class="news_posts-3"></div>
<div class="news_posts-2"></div>
My ajaxLoop:
jQuery(function($){
var page = 1;
var loading = true;
var $window = $(window);
var cat = [6,3,2];
var load_posts= jQuery.each(cat, function(){
var $content = $(".news_posts-" + this);
$.ajax({
type : "GET",
data : {numPosts: 2, pageNumber: page, cat: this},
dataType : "html",
url : "http://127.0.0.1:4001/wordpress/wp-content/themes/twentyeleven-child-theme/loopHandler.php",
beforeSend : function(){
if(page != 1){
$content.append('<div id="temp_load" style="text-align:center">\
<img src="/images/ajax-loader.gif" />\
</div>');
}
},
success : function(data){
$data = $(data);
if($data.length){
$data.hide();
$content.append($data);
$data.fadeIn(500, function(){
$("#temp_load").remove();
loading = false;
});
} else {
$("#temp_load").remove();
}
},
error : function(jqXHR, textStatus, errorThrown) {
$("#temp_load").remove();
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
});
$window.scroll(function() {
var content_offset = $content.offset();
console.log(content_offset.top);
if(!loading && ($window.scrollTop() +
$window.height()) > ($content.scrollTop() + $content.height() + content_offset.top)) {
loading = true;
page++;
load_posts();
}
});
load_posts();
});
Part of loopHandler.php:
$numPosts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;
$cat = (isset($_GET['cat'])) ? $_GET['cat'] : 0;
echo $numPosts;
echo $page;
query_posts(array(
'posts_per_page' => $numPosts,
'paged' => $page,
'cat' => $cat
));
I tried use simple array containing categories numbers but it doesn't work. Depends on
data : {numPosts: X, pageNumber: page, cat: this},
there is X post displaying in each column (same posts from first category).
I guess I need to use JSON, which I tried, but it was total disaster (I don't know how to put it together). I just need to call AJAX for three different arguments.
Thanks for any help
Well, there are various ways you can go about this.
One way is looping over your categories client side first, and make separate request per category. This is what you are essentially doing in your code. You are iterating over an array of categories and making a request for each.
Another way is to pass that array of categories to your handler. All you need to do is modify your handler to accept an array of integers or categories. Then you can return a JSON object. But this involves a lot more editing and on top of that it does not solve the issue of having different sizes and heights for each section.
Thus, below, I have modified the code a little bit to also keep track of multiple sections. There are just a few small edits we need:
Each section needs to have a category number, pagination number, content section, and a flag whether its loading or not. Each needs to be stored in a single list for tracking.
We need to iterate over each category to initialize it.
We need to iterate over each category on window scroll and check if the next item should be loaded
We need to make sure that each request relates to the requested category
Start by modifying your divs a little (this is just a matter of preference, i prefer storing metadata like this in an attribute instead of a class):
<div class="news_posts" data-category="6"></div>
<div class="news_posts" data-category="3"></div>
<div class="news_posts" data-category="2"></div>
Here's a modified JS (please be aware that I changed up some variable and function names):
jQuery(function($){
var $window = $(window);
var cats = [];
var contentDivs = $(".news_posts");
var initializeCats = function(){
// adds category objects to a list for tracking
for(var i = 0; i < contentDivs.length; i++){
var catNum = $(contentDivs[i]).attr("data-category");
var cat = {
catNum : catNum,
catPage : 1,
loading : true,
catDiv : $(contentDivs[i]);
};
cats.push(cat);
load_post(cat);
}
};
var load_post = function(cat) {
$.ajax({
type : "GET",
data : {
numPosts : 2,
pageNumber : cat.catPage,
cat : cat.catNum
},
dataType : "html",
url : "http://127.0.0.1:4001/wordpress/wp-content/themes/twentyeleven-child-theme/loopHandler.php",
beforeSend : function(){
if(page != 1){
// this was a bad idea when i wrote the article originally
// never concatenate strings on multiple lines by escaping
// the carriage return
// $content.append('<div id="temp_load" style="text-align:center">\
// <img src="/images/ajax-loader.gif" />\
// </div>');
cat.catDiv.append("<div class='temp_load' style='text-align:center'>" +
"<img src='/images/ajax-loader.gif' />" +
"</div>");
}
},
success : function(data){
$data = $(data);
if($data.length){
$data.hide();
cat.catDiv.append($data);
$data.fadeIn(500, function(){
cat.catDiv.find(".temp_load").remove();
cat.loading = false;
});
} else {
cat.catDiv.find(".temp_load").remove();
}
},
error : function(jqXHR, textStatus, errorThrown) {
cat.catDiv.find(".temp_load").remove();
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
});
var onWindowScroll = function(){
for(var i = 0; i < cats.length; i++){
var cat = cats[i];
var contentDiv = cat.catDiv;
var content_offset = contentDiv.offset();
if( !cat.loading &&
($window.scrollTop() + $window.height()) >
(contentDiv.scrollTop() + contentDiv.outerHeight() + content_offset.top)
) {
cat.loading = true;
cat.catPage++;
load_post(cat);
}
}
}
initializeCats();
$window.scroll(onWindowScroll);
});
The PHP file is pretty much the same, just comment out the echo $numPosts line:
$numPosts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;
$cat = (isset($_GET['cat'])) ? $_GET['cat'] : 0;
// echo $numPosts;
echo $page;
query_posts(array(
'posts_per_page' => $numPosts,
'paged' => $page,
'cat' => $cat
));
This is just something quick I whipped up. I HAVE NOT TESTED IT. Try it out, watch out for syntax errors, and cross your fingers :). I hope this will work for you and if it does not, we can look into modifying it so that it does.

WooCommerce plugin , add variation to cart via Ajax

Im looking for a solution to add a product variation via Ajax.
As i found out all the WooCommerce basic functions allow adding a product to the cart only if it is not a variation item.
im using <?php echo woocommerce_template_loop_add_to_cart() ?> to display the add to cart button but this button is a regular submit button.
how can i make a variable item use the Ajax add to cart ?
I created and AJAX add to cart for variable products like this:
Sorry about the delay, here is the expanded answer:
I included a new js file called added-to-cart.js and the file contains the following code. There is some extra code for handling a popup and also increasing the cart counter which you might want to remove.
/* Begin */
jQuery(function($) {
/* event for closing the popup */
$("div.close").hover(
function() {
$('span.ecs_tooltip').show();
},
function () {
$('span.ecs_tooltip').hide();
}
);
$("div.close").click(function() {
disablePopup(); // function close pop up
})
$("a.close").click(function() {
disablePopup(); // function close pop up
});
$(this).keyup(function(event) {
if (event.which == 27) { // 27 is 'Ecs' in the keyboard
disablePopup(); // function close pop up
}
});
$("div#backgroundPopup").click(function() {
disablePopup(); // function close pop up
});
$('a.livebox').click(function() {
//alert('Hello World!');
return true;
});
setAjaxButtons(); // add to cart button ajax
function loading() {
$("div.loader").show();
}
function closeloading() {
$("div.loader").fadeOut('normal');
}
// AJAX buy button for variable products
function setAjaxButtons() {
$('.single_add_to_cart_button').click(function(e) {
var target = e.target;
loading(); // loading
e.preventDefault();
var dataset = $(e.target).closest('form');
var product_id = $(e.target).closest('form').find("input[name*='product_id']");
values = dataset.serialize();
$.ajax({
type: 'POST',
url: '?add-to-cart='+product_id.val(),
data: values,
success: function(response, textStatus, jqXHR){
loadPopup(target); // function show popup
updateCartCounter();
},
});
return false;
});
}
function updateCartCounter() {
var counter = $('.widget_shopping_cart_content').text().replace(/\s/g, '');
if (counter == '') {
$('.widget_shopping_cart_content').text("1");
}
else {
$('.widget_shopping_cart_content').text(++counter);
}
}
var popupStatus = 0; // set value
function loadPopup(target) {
var currentPopup = $(target).parents(".single_variation_wrap").find("#toPopup");
var currentBgPopup = $(target).parents(".single_variation_wrap").find("#backgroundPopup");
if(popupStatus == 0) { // if value is 0, show popup
closeloading(); // fadeout loading
currentPopup.fadeIn(0500); // fadein popup div
currentBgPopup.css("opacity", "0.7"); // css opacity, supports IE7, IE8
currentBgPopup.fadeIn(0001);
popupStatus = 1; // and set value to 1
}
}
function disablePopup() {
if(popupStatus == 1) { // if value is 1, close popup
$(".single_variation_wrap > div:nth-child(2)").fadeOut("normal");
$(".single_variation_wrap > div:nth-child(4)").fadeOut("normal");
popupStatus = 0; // and set value to 0
}
}
}); // jQuery End

Resources