AJAX loop for WordPress (posts from different categories) - ajax

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.

Related

How to pass all loop value and pass to ajax?

Why it returns only the last number of my database? I wanted to return all value inside the div. Help me.
Ajax
$.ajax({
url : 'Test.php',
method : 'post',
data : {id: id},
success : function(response)
{
var x = $.parseJSON(response);
for (var a in b)
{
$('#allValue').html(b[a]);
}
}
});
PHP
if(isset($_POST['id']))
{
$query = mysqli_query($conn, "SELECT * FROM tbl_reservation");
while ($row = mysqli_fetch_array ($query))
{
$result[] = array($row['ID_reservation']);
}
echo json_encode($result);
}
By doing
$("#element").html("TEST");
The HTML method removes any existing content and replaces it with "TEST". If you want to append text you could first get the HTML value, but better yet:
var x = $.parseJSON(response);
var text = "";
for (var a in b)
{
text += b[a];
}
$('#allValue').html(text);

Materialize autocomplete : Why AJAX called before entering any character?

I'm using autocomplete with materialize and i'm retrieving the data with ajax call, it works fine but when i want to call ajax only after entering caracters(using onkeyup event), the drop down list will not be showing correctly !!!!
Before i forget please help me to show a "NOT FOUND" in the drop down list if no data founded (because my else condition doesn't work). here is my code and thanks a lot in advance :
$(document).ready(function() {
var contents = $('#autocomplete-input')[0];
contents.onkeyup = function (e) {
$.ajax({
type: 'GET',
url: Routing.generate('crm_search_lead', {"search":
$(this).val()}),
success: function (response) {
var contacts = {};
if (true === response.success) {
var result = response.result;
for (var i = 0; i < result.length; i++) {
var lastName = result[i].lastName ?
result[i].lastName : '';
var firstName = result[i].firstName ?
result[i].firstName : '';
contacts[lastName + " " + firstName] = null;
}
$('input.autocomplete').autocomplete({
data: contacts,
minLength: 2,
});
} else {
$('input.autocomplete').autocomplete({
data: {
"NOT FOUND": null
}
});
}
}
});
}
});
Hi people :) i resolve it by changing onkeyup() with focus() and it's totally logical because with onkeyup() the droplist will appear and disappear very quickly on every key entered.

Parsing JSON with AJAX - show random item of the JSON and update after an amount of time

I'm able to parse JSON with ajax, but at the moment it shows all the names out of the JSON.
I want only one name viewed and after an amount of time I want another one viewed and so on..
Ajax code:
$(document).ready(function(){
parseJson();
});
function parseJson(){
$.ajax({
url : 'data/members.json',
dataType : 'json',
success : function(data) {
succes(data);
},
error: function(){
window.alert("error");
}
});
};
function succes(dataObj){
var counter = 1;
$.each(dataObj.Members.Member, function(indexData, valueData){
var htmlString = "";
htmlString += '<article class="memberInfo" data-object="' + counter + '">';
htmlString += "<div class=''><p>" + valueData.Firstname + ' ' + valueData.Surname + "</p></div>";
htmlString += "</article>";
$("#members").append(htmlString);
counter++;
});
}
Rather than use .append you can use .html and set a staggering timeout so that it cycles through the names that get displayed:
var timer = 0;
$.each(...
setTimeout(function () {
var htmlString = "";
/* snip */
$("#members").html(htmlString);
}, timer + (indexData * 2000));
});

Masonry, Isotope and Ajax Load

I have set up a test site using masonry and am using isotope for sorting.
I have also set up a button at the bottom that the user can click to ajax load more posts.
I have the ajax loading working properly, but when the new posts get appended to the bottom of the container the first four posts at the top all shift out of place. If I keep clicking 'load more' all subsequent posts that load load perfectly and nothing else shifts. It seems to be only the first four posts, on the first ajax load.
Anyone know why this is happening?? It's driving me crazy
Ajax Load File
// ajaxLoop.js
jQuery(function($){
var page = 1;
var loading = true;
var $window = $(window);
var $ajaxLoadMoreButton = $("body.blog .ajaxLoadMoreButton");
var $content = $("body.blog #container");
var load_posts = function(){
$.ajax({
type : "GET",
data : {numPosts : 1, pageNumber: page},
dataType : "html",
url : "wp-content/themes/twentytwelve/loopHandler.php",
beforeSend : function() {
if(page !=1) {
}
},
success : function(data){
$data = $(data);
if($data.length){
$data.hide();
$content.append($data).masonry('reload');
$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);
}
});
}
$ajaxLoadMoreButton.click(function() {
loading = true;
page++;
load_posts();
});
});
To anyone else having this issue, after digging for hours through documentation and asking for help on SO and other sites, I have resolved the issue. The issue apparently lies within -webkit browsers and the transform property that is placed on masonry elements after appending new ones.
I used this as a reference:
http://isotope.metafizzy.co/docs/help.html#disabling_transforms
and then I used this code to disable all transforms on elements:
$("#container").isotope({
itemSelector : ".brick",
transformsEnabled: false, // disables all transform properties
getSortData : {
name : function () {
$tag = $("#container").find("a[rel=tag]").text();
}
}
});

JQueryMobile: page with data (from ajax) doesn't change

function returnQueryResultJson(url,callback) {
return $.ajax({
url: url,
type: "GET",
dataType: "json",
success: function(response) {
callback(response);
}
});
}
function showCategory(url,hash, options) {
var cat = hash.replace(/.*category=/, "");
if (cat == '#page1') {
cat = '';
}
var a = returnQueryResultJson('http://www.placetowebservice.nl/categories.php?category=' + cat,function(res) {
var
category = res,
pageSelector = hash.replace(/\?.*$/, ""),
$page = $(pageSelector),
$header = $page.children(":jqmData(role=header)"),
$content = $page.children(":jqmData(role=content)"),
markup = '<ul data-role="listview" data-theme="c" data-dividertheme="b">';
var cItems = category;
var headername = category.name;
var numItems = cItems.length;
if (cat == '') {
markup = '<ul data-role="listview" data-theme="c" data-dividertheme="b" style="min-height:100%;">';
}
for (var i=0;i<numItems;i++) {
markup += '<li><h3>' + cItems[i].title + '</h3><p>' + cItems[i].description + '</p></li>';
}
markup += "</ul>";
$header.find("h1").html(headername);
$content.html(markup);
$page.page();
$content.find(":jqmData(role=listview)").listview();
options.dataUrl = url;
options.changeHash = true;
options.reloadPage = true;
console.log($page);
$.mobile.changePage($page, options);
//}
});
}
$(document).bind("pagebeforechange", function(e,data) {
if (typeof data.toPage === "string") {
var
uz = $.mobile.path.parseUrl(data.toPage),
re = /^#category-item/,
re2 = /^#page1/
;
if (uz.hash.search(re) !== -1 || uz.hash.search(re2) !== -1) {
showCategory(uz.href,uz.hash,data.options);
e.preventDefault();
}
}
});
I have got this code, and it works pretty good (first time). I first load a page with:
$(document).ready(function(){
$.mobile.changePage('index.html#page1',{ dataUrl: "index.html#page1?category=", transition: "fade" });
});
It works, it loads the ajax-data in the page with id="page1".
Then I click on a link (category 1) and it shows the second page (with id="category-item") and fills it with the right data (category 1: sub 1, category 1: sub 2). Then I go back and it shows the categories again.
Now the problem appears, when I click on the next category (category 2). When I go to that page, it gives the right data from ajax (I used console.log to check this), but the data on the screen remains the data from category 1.
So the content from the first category you click on remains, even though you afterwards went to another category. It will remain showing the category you first clicked on.
What am I doing wrong?
It worked When I did this:
$page.page();
$page.trigger('create'); // added this one
$content.find(":jqmData(role=listview)").listview();
$content.find(":jqmData(role=listview)").listview("refresh"); // added this one

Resources