I'm trying to AJAX loading posts in my blog, I've successfully get it to work this way:
the page displays 3 posts on page load, then the visitor can get 3 more posts each time he clicks the button "LOAD MORE".
Now I want to load 9 posts on page load but keep 3 posts with each click on "LOAD MORE" button.
A problem occurs with the page number value in the WPQuery, it's getting the same 3 posts which were already displayed.
how can I prevent posts duplication?
Please check it here at my temp website
[note that I have less than 9 posts at the category page, it should load all of them]
(function($) {
$(document).ready(function(){
var $content = $('#list-content');
var $btnLoad = $('#btnLoad');
var loading = true;
var page = 1;
var load_posts = function($count){
var post_id = $(this).attr( 'id' );
/** Ajax Call */
$.ajax({
cache : false,
timeout : 8000,
url : php_array.admin_ajax,
type : "POST",
data : {action:'main_query', numPosts : $count, pageNumber: page, condition: php_array.condition, val: php_array.val},
beforeSend : function() {
$('#loadimg').slideToggle("fast");
$btnLoad.prop("disabled",true);
},
success : function(data, textStatus, jqXHR ){
var $data = $( data );
if($data.length){
$content.append( $data );
$btnLoad.prop("disabled",false);
}
else{
$btnLoad.html("That's it");
$btnLoad.prop("disabled",true);
}
},
error : function( jqXHR, textStatus, errorThrown ){
if(t==="timeout") {
alert("Server is too slow, try again later");
} else {
alert(t);
}
console.log( 'ajaxLoop.js: The following error occured: ' + textStatus, errorThrown );
},
complete : function( jqXHR, textStatus ){
$('#loadimg').slideToggle("fast");
loading = false;
page++;
}
});
}
$btnLoad.on("click", function(e) {
e.preventDefault();
loading = true;
load_posts(3);
});
load_posts(9); //load the first elements
});
})(jQuery);
PHP code:
function main_query_init() {
/** Made Query */
$numPosts = (isset($_POST['numPosts'])) ? $_POST['numPosts'] : 0;
$page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
$condition = (isset($_POST['condition'])) ? $_POST['condition'] : '';
$val = (isset($_POST['val'])) ? $_POST['val'] : '';
$args = array(
'posts_per_page'=> $numPosts,
'paged' => $page,
);
if($condition != ''){
$args[$condition] = $val;
}
$post_query = new WP_Query( $args );
if ($post_query->have_posts()) : while ($post_query->have_posts()) : $post_query->the_post();
You are probably looking for the offset parameter for WP_Query. Setting it to 3 will cause it to skip the first 3 results when using posts_per_page and paged.
The other option is to specify the post_ids that you don't want explicitly using the post__not_in parameter, but this will require passing the array of values to exclude with each request - you might be able to get away with just passing in the first 3 IDs, but I would go with offset.
The key is var currCount = $data.filter('article').length;
where I store the current count of posts from ajax response.
Since I ask for extra 3 posts every load button click, then if((currCount % 3) == 0) will tell me if it got 3 posts otherwise there are no more posts and there is no need to increment page counter.
success : function(data, textStatus, jqXHR ){
var $data = $( data );
var currCount = $data.filter('article').length;
totalCount += currCount;
if(currCount > 0){
$content.append( $data );
$btnLoad.prop("disabled",false);
if((currCount % 3) == 0)
page += currCount / 3;
else
page += (parseInt(totalCount/3) + 1);
return;
}
$btnLoad.html("That's it");
$btnLoad.prop("disabled",true);
},
Related
I am using AJAX to load more products on a WooCommerce archive. I have used AJAX to "Load More" once before on this page. I have used the same code for the most part, just altered the WP_Query arguments to suit my needs. I can't understand why my code doesn't work.
JS
/**
* AJAX Load (Lazy Load) events
*/
$('#load-more').click( function(e){
e.preventDefault();
ajax_next_posts()
$('body').addClass('ajaxLoading');
});
var ajaxLock = false; // ajaxLock is just a flag to prevent double clicks and spamming
if( !ajaxLock ) {
function ajax_next_posts() {
ajaxLock = true;
// How many posts there's total
var totalPosts = parseInt( jQuery( '#found-posts' ).text() );
// How many have been loaded
var postOffset = jQuery( 'li.product' ).length
// How many do you want to load in single patch
var postsPerPage = 1;
// Ajax call itself
$.ajax({
method: 'POST',
url: leafshop.ajax_url,
data: {
action: 'ajax_next_posts',
post_offset: postOffset,
posts_per_page: postsPerPage,
product_cat: cat_id
},
dataType: 'json'
})
.done( function( response ) { // Ajax call is successful
// console.log( response );
// Add new posts
jQuery( '.product-grid' ).append( response[0] );
// Log SQL query
jQuery( '#query > pre' ).text( response[2] );
// Update the count of total posts
// jQuery( '#found-posts' ).text( response[1] );
ajaxLock = false;
console.log( 'Success' );
$('body').removeClass('ajaxLoading');
// How many posts there's total
var totalPosts = parseInt( jQuery( '#found-posts' ).text() );
console.log( "Total Posts: " + totalPosts );
// How many have been loaded
var postOffset = jQuery( 'li.product' ).length
console.log( "Posts currently showing: " + postOffset );
// Hide button if all posts are loaded
if( totalPosts < postOffset + ( 1 * postsPerPage ) ) {
jQuery( '#load-more' ).fadeOut();
}
})
// .fail( function() {
.fail( function(jqXHR, textStatus, errorThrown) { // Ajax call is not successful, still remove lock in order to try again
ajaxLock = false;
console.log(XMLHttpRequest);
console.log(textStatus);
console.log(errorThrown);
console.log( 'Failed' );
});
}
}
PHP
<?php
/**
* Load next 12 products using AJAX
*/
function ajax_next_posts() {
global $wpdb;
// Build query
$args = array(
'post_type' => 'product'
);
// Get offset
if( !empty( $_POST['post_offset'] ) ) {
$offset = $_POST['post_offset'];
$args['offset'] = $offset;
// Also have to set posts_per_page, otherwise offset is ignored
$args['posts_per_page'] = 12;
}
// Get posts per page
if( !empty( $_POST['posts_per_page'] ) ) {
// Also have to set posts_per_page, otherwise offset is ignored
$args['posts_per_page'] = $_POST['posts_per_page'];
}
// Set tax query if on cat page
if( !empty( $_POST['product_cat'] ) ){
$args['tax_query'] = array(
'taxonomy' => 'product_cat',
'terms' => array( (int)$_POST['product_cat'] ),
'field' => 'id',
'operator' => 'IN',
'include_children' => 1
);
}
$count_results = '0';
$ajax_query = new WP_Query( $args );
// Results found
if ( $ajax_query->have_posts() ) {
$count_results = $ajax_query->found_posts;
// Start "saving" results' HTML
$results_html = '';
ob_start();
while( $ajax_query->have_posts() ) {
$ajax_query->the_post();
echo wc_get_template_part( 'content', 'product' );
}
// "Save" results' HTML as variable
$results_html = ob_get_clean();
}
// Build ajax response
$response = array();
// 1. value is HTML of new posts and 2. is total count of posts
global $wpdb;
array_push ( $response, $results_html, $count_results, $wpdb->last_query );
echo json_encode( $response );
// Always use die() in the end of ajax functions
die();
}
add_action('wp_ajax_ajax_next_posts', 'ajax_next_posts');
add_action('wp_ajax_nopriv_ajax_next_posts', 'ajax_next_posts');
The AJAX call runs successfully but doesn't return what I'd expect it to. I'd expect it to return the next product from the current category, instead it returns a product from a different category. The development site is accessible on http://leaf.kalodigital.co.uk and I have been using the "Black Tea" page in my testing. Any help would be greatly appreciated.
Method
After some further research, I found that WooCommerce contains a class names WC_Poduct_Query. Following their documentation, found here, I rebuilt my query. This was working in the sense that it was querying for the correct products and returns the ones I'd expect it to as an array of WC_Product_Variable Objects. I proceeded to, within a foreach loop, use setup_postdata( $post ); to set the product Objects up so that I could use the wc_get_template_parts(); function to call the content-product.php template to format the output of the data. I found that this didn't work, although I couldn't figure to why this was the case, using setup-postdata(); was causing the object to turn into [{id:0,filter:raw},{id:0,filter:raw}]. I imagine this would be related to the WC_Product_Variable Objects not matching the expect format that setup_postdata(); usually expects from a WP_Post Object.
Nonetheless, I reverted to using WP_Query for my query, rebuilt the query script from scratch and, would you believe it, everything worked as expected to. Below is my working code to AJAX load the next "bunch" of products on any WooCommerce Archive page, at the click of a button.
Code
JS
/**
* AJAX Load (Lazy Load) events
*/
//-- Settings
// How many do you want to load each button click?
var postsPerPage = 12;
//-- /Settings
// How many posts there's total
var totalPosts = parseInt( jQuery( '#found-posts' ).text() );
// if( totalPosts == postOffset ) {
// jQuery( '#load-more' ).fadeOut();
// }
$('#load-more').click( function(e){
e.preventDefault();
// Get current category
var cat_id = $(this).data('product-category');
ajax_next_posts( cat_id );
$('body').addClass('ajaxLoading');
});
var ajaxLock = false; // ajaxLock is just a flag to prevent double clicks and spamming
if( !ajaxLock ) {
function ajax_next_posts( cat_id ) {
ajaxLock = true;
// How many have been loaded
var postOffset = jQuery( 'li.product' ).length;
// Ajax call itself
$.ajax({
method: 'POST',
url: leafshop.ajax_url,
data: {
action: 'ajax_next_posts',
post_offset: postOffset,
posts_per_page: postsPerPage,
product_cat: cat_id
},
dataType: 'json'
})
.done( function( response ) { // Ajax call is successful
// Add new posts
jQuery( '.product-grid' ).append( response[0] );
// Update Post Offset
var postOffset = jQuery( 'li.product' ).length;
ajaxLock = false;
console.log( 'Success' );
$('body').removeClass('ajaxLoading');
// How many posts there's total
console.log( "Total Posts: " + totalPosts );
// How many have been loaded
var postOffset = jQuery( 'li.product' ).length
console.log( "Posts on Page: " + postOffset );
// Hide button if all posts are loaded
if( ( totalPosts - postOffset ) <= 0 ) {
jQuery( '#load-more' ).fadeOut();
}
})
// .fail( function() {
.fail( function(jqXHR, textStatus, errorThrown) { // Ajax call is not successful, still remove lock in order to try again
ajaxLock = false;
console.log(XMLHttpRequest);
console.log(textStatus);
console.log(errorThrown);
console.log( 'Failed' );
});
}
}
PHP
<?php
/**
* Load next 12 products using AJAX
*/
function ajax_next_posts() {
global $product;
// Build Query
$args = array(
'post_type' => 'product',
'posts_per_page' => (int)$_POST['posts_per_page'],
'orderby' => 'title',
'order' => 'ASC',
'offset' => (int)$_POST['post_offset'],
);
if( !empty( $_POST['product_cat'] ) ) {
$args['tax_query'] = array(
'relation' => 'AND',
array (
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $_POST['product_cat'],
'operator' => 'IN'
),
);
}
$count_results = '0';
$ajax_query = new WP_Query( $args );
// Results found
if( $ajax_query->have_posts() ){
// Start "saving" results' HTML
$results_html = '';
ob_start();
while( $ajax_query->have_posts() ) {
$ajax_query->the_post();
echo wc_get_template_part( 'content', 'product' );
}
wp_reset_postdata();
// "Save" results' HTML as variable
$results_html = ob_get_clean();
} else {
// Start "saving" results' HTML
$results_html = '';
ob_start();
echo "none found!";
// "Save" results' HTML as variable
$results_html = ob_get_clean();
}
// Build ajax response
$response = array();
// 1. value is HTML of new posts and 2. is total count of posts
array_push ( $response, $results_html );
echo json_encode( $response );
// Always use die() in the end of ajax functions
die();
}
add_action('wp_ajax_ajax_next_posts', 'ajax_next_posts');
add_action('wp_ajax_nopriv_ajax_next_posts', 'ajax_next_posts');
Use Cases
By refactoring the supplied AJAX code, it would be possible to turn this solution into an "infinite scrolling" system as opposed to a "Load More" button solution. Please feel free to reuse this code where it may see fit!
My ajax function for saving post is making multiple requests, and i can't understand why. I tried searching for the duplicate elements, that may cause double clicking, but there is no duplicates. And sometimes it posts on ONE click 4 times
Here is the screenshot of multiple ajax post, when i click on #order_save button,
My #order_save button, when i search for the order_save in the DOM tree, the first match is this element. (original click element)
And the second match(2 of 2) for the order_save is at jquery code (which is normal)
jQuery(function($) {
$(document).on('click','#order_save',function(){
var order_title = $('#client-order-title').val();
var order_comment = $('#client-comment').val();
var order_date = $('#order_date_till').val();
var price_input = $('#order_price').val();
var order_price;
var order_attachments = [];
if($('#order_price_on_deal:checked').val() == 'foo') {
order_price = 'foo';
}else{
order_price = price_input;
}
if(!order_title) {
$('#client-order-title').addClass('has-error');
return false;
}else{
$('#client-order-title').removeClass('has-error');
}
if(!order_comment) {
$('#client-comment').addClass('has-error');
return false;
}else{
$('#client-comment').removeClass('has-error');
}
$('#files_public .order-attachment').each(function() {
var attachment_link = $(this).find('a').attr('href');
var attachment_title = $(this).text();
order_attachments.push({
'file_url' : attachment_link,
'file_name' : attachment_title
});
});
$.ajax({ // Line 68 is here
url: my_ajax.url,
type: "POST",
data: {
'action' : 'xx_order_saving',
'order_title' : order_title,
'order_comment' : order_comment,
'order_date' : order_date,
'order_price' : order_price,
'order_attachment' : order_attachments,
'order_type' : 'public_order'
},
dataType: "json",
success: function(response){
if(response.html) {
$('#currentOrder').html(response.html);
}
}
})
});
});
PHP handler in my functions php (working fine)
function xx_order_saving() {
// posting data here
if($order_title && $order_comment) {
$new_post_a = array(
'post_type' => 'orders',
'post_title' => $order_title,
'post_status' => 'publish'
);
$new_order = wp_insert_post($new_post_a);
if($new_order) {
wp_update_post( array( 'ID' => $new_order, 'post_name' => $new_order ) );
}
$template_file = 'xxx-order-saved.php';
ob_start();
include(locate_template($template_file,false,false));
$page_template = ob_get_contents();
ob_end_clean();
$response['html'] = $page_template;
wp_send_json($response);
}
}
add_action('wp_ajax_xx_order_saving','xx_order_saving');
add_action('wp_ajax_nopriv_xx_order_saving','xx_order_saving');
The template file with the jquery code above is loaded dynamically using this function
function load_frame() {
$option = $_POST['option'];
if($option){
$template_file = 'xxxx-'.$option.'.php';
ob_start();
include(locate_template($template_file,false,false));
$page_template = ob_get_contents();
ob_end_clean();
$response['html'] = $page_template;
wp_send_json($response);
}
}
Sometimes it works just fine, sending one request, saving one post, sometimes it posts 4 or 2 times as shown in the screenshot above.
Here is what seems to cause the problem:
If there is order-attachments, for example one attachment it will send two requests (save two posts) if there is two attachments it will send One request, if there is three attachments it will send 4 requests, if there is 5 it sending One again. I just don't get it. Any help will be appreciated
<div id="files_public" class="form-group">
<span class="list-group-item order-attachment">Image.png
...</span>
</div>
Change
$(document).on("click", "#order_save", function () {
to
$("#order_save").click(function () {
I've seen some answers to this question on this site already, but i still haven't been able to implement it as i want to for 2 days now. I'm sort of a beginner so a very clear explanation would be of great help,
i have a mysql database of some data, i want to read from a table and display 30 rows at a time, when the user scrolls to the end of the page, i want to load another 30 rows (i have been able to do the first 30, but loading the remaining is a challenge for me).
i already have this:
$(document).ready(function(){
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() -$(window).height()) {
//ive tried all sorts of things here it just doesnt work
}
});
also an example of the php file that loads the next contents would help,
i'm using php and mysqli
thanks a lot in advance.
so this is my loadmore.php, its for the functionality, haven't styled the output:
<?php
require_once 'functions.php'; //my databse connection is in this file
//i created a function queryMysql($query) in functions.php, thats what is used here
$result = queryMysql("SELECT * FROM articles WHERE live='1' ORDER BY created DESC LIMIT $start, 30");
$num = $result->num_rows;
for ($j = 0 ; $j < $num ; ++$j){
$row = $result->fetch_array(MYSQLI_ASSOC);
$title = $row['title'];
$subtitle = $row['subtitle'];
echo "$title<br />$subtitle";
}?>
for the ajax, i changed it to the first answer i got here, but all my attempts have looked like this:
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
type: method,
data: {}, //Your data
url: 'loadmore.php',
async: true,
success: function (data, textStatus, jqXHR) {
$('#article-inro-hold').append(data);
},
error: function (jqXHR) {
//Error handler
}
});
}
});
Try to implement jquery ajax, something rough like this:
$(document).ready(function () {
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
type: method,
data: {}, //Your data
url: 'your/url/to/get/more/content/from',
async: true,
success: function (data, textStatus, jqXHR) {
$('#myDiv').append(data);
},
error: function (jqXHR) {
//Error handler
}
});
}
});
});
You have to make an ajax call for each time, when you scroll amount get up, nearer to document height. Along with you also have to manage your offset, otherwise you will get duplicate records (You can use hidden field for that), and pass it each time in your ajax call.
<div id="ajax-response"></div>
<input type="hidden" value="0" id="offset" />
<script>
$(document).ready(function(){
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
url: 'requesthandler.php',
type: 'post',
data: {
task: 'show-more',
offset: document.getElementById('offset').value
},
success: function(response){
jsonObj = $.parseJSON(response);
$('#ajax-response').append(jsonObj.html);
document.getElementById('offset').value = jsonObj.offset;
}
})
}
});
});
and requesthandler.php will look like:
if($_POST['task'] == 'show-more'){
$offset = (int) $offset;
$sql = "SELECT * FROM table limit $offset, 10";
$data = '';
foreach ($conn->query($sql) as $row) {
$data .= "<div>$row['column']</div>";
}
echo json_encode(array(
'offset' => ($offset + 10),
'html' => $data,
))
}
$query = $db->query("SELECT * FROM bags ORDER BY id DESC LIMIT 7");
Can we use $_POST here to get only needed information.
$limit=($_POST["bag"]);
$query = $db->query("SELECT * FROM bags WHERE id = '.$limit.' ORDER BY id DESC LIMIT 7");
I have a function that dynamicaly loads more posts after clicking the button and a LoopHandler.php that is displaying posts. Everything works perfect, apart from that the loop is always displaying all of the posts. So if I am on the category page it displays posts from all of the categories. Why is it happening so? How to fix it?
// ajaxLoop.js
jQuery(function($){
var page = 1;
var loading = true;
var $window = $(window);
var $content = $("body #post-stream .block");
var load_posts = function(posts, row){
$.ajax({
type : "GET",
data : {numPosts : posts, pageNumber: page, postsInRow: row},
dataType : "html",
url : "../loopHandler.php",
beforeSend : function(){
$content.append('<div id="temp_load" style="text-align:center; clear: both; padding: 30px 0;">\
<img src="http://cayennestudio.pl/segritta/wp-content/themes/segritta-ajax/css/img/ajax-loader.gif" />\
</div>');
},
success : function(data){
$data = $(data);
$(window).scrollTop($(window).scrollTop()-1);
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);
}
});
page++;
}
var load_szorts = function(posts, row){
$.ajax({
type : "GET",
data : {numPosts : posts, pageNumber: page, postsInRow: row},
dataType : "html",
url : "http://cayennestudio.pl/segritta/wp-content/themes/segritta-ajax/loopHandlerSzorts.php",
beforeSend : function(){
},
success : function(data){
$data = $(data);
$data.hide();
$content.append($data);
$data.fadeIn(500, function(){
loading = false;
});
},
error : function(jqXHR, textStatus, errorThrown) {
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
page++;
}
if ( $('body.home').length ) {
load_posts(4, 2);
$('.load-more').click(function(){
load_posts(4, 2);
});
};
if ( $('body.category').length ) {
load_posts(9, 3);
$('.load-more').click(function(){
load_posts(9, 3);
});
};
if ( $('body.post-type-archive-szort').length ) {
load_szorts(8, 4);
$('.load-more').click(function(){
load_szorts(4, 4);
});
};
});
LoopHandler.php
<?php
// Our include
define('WP_USE_THEMES', false);
require_once('../../../wp-load.php');
// Our variables
$numPosts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;
query_posts(array(
'posts_per_page' => $numPosts,
'paged' => $page,
));
global $var_counter;
global $var_row;
$var_counter = 0;
$var_row = (isset($_GET['postsInRow'])) ? $_GET['postsInRow'] : 2;
// our loop
if ( have_posts() ) :
while ( have_posts() ) : the_post();
get_template_part( 'content', get_post_format() );
endwhile;
else:
get_template_part( 'content', 'none' );
endif;
wp_reset_query();
?>
First of all it should go to WordPress.StackExchange, I guess.
And going back to your problem...
First problem: Bad AJAX handling
You shouldn't create your own PHP files to process AJAX requests in WordPress. WP has it's own mechanisms to process AJAX requests and you should use them for compatibility reasons.
You can read more on this topic here: http://codex.wordpress.org/AJAX_in_Plugins
You just need to create a filter with correct name and call AJAX requests with correct action value...
Second Problem: Always all posts
You don't pass current category anywhere in your AJAX request and you don't put it in your WP_Query.
You should pass current category ID in your AJAX request like so:
$.ajax({
type : "GET",
data : {numPosts : posts, pageNumber: page, postsInRow: row, currentCat: currentCat}, // of course you need to make sure that currentCat variable contains the ID of current category or 0 otherwise
dataType : "html",
...
And then process it in your PHP code like so:
$args = array(
'posts_per_page' => $numPosts,
'paged' => $page,
);
if ( isset($_GET['currentCat']) && $_GET['currentCat'] ) {
$args['cat'] = $_GET['currentCat'];
}
query_posts($args);
I've got a problem which I can't seem to solve.
I'm currently implementing a an AJAX-function similar to the one Twitter uses - that fetch new posts on scrolling.
The jQuery looks something like this:
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()){
$('div#ajaxloader').show();
$.ajax({
url: "loader.php?lastid=" + $(".container:last").attr("id"),
success: function(html){
if(html){
$("#main").append(html);
$('div#ajaxloader').hide();
}else{
$('div#ajaxloader').html('No more posts to show.');
}
}
});
}
});
Now the problem; if the user scrolls really fast and the database is doing it's work quickly - the jQuery doesn't seem to be able to send the correct id as a query fast enough - which results in double-posts.
Anyone have a good idea on how to prevent this?
Try This:
var runningRequest = 0;
$(window).scroll(function(){
if(runningRequest <1){
if($(window).scrollTop() == $(document).height() - $(window).height()){
runningRequest++;
$('div#ajaxloader').show();
$.ajax({
url: "loader.php?lastid=" + $(".container:last").attr("id"),
success: function(html){
runningRequest--;
if(html){
$("#main").append(html);
$('div#ajaxloader').hide();
}else{
$('div#ajaxloader').html('No more posts to show.');
}
}
error: function(){runningRequest--;}
});
}
}
});
I would set a boolean to true right before making my request, and whenever the request completes I'd set it back to false. Then I'd wrap the code that makes the request in a check for whether that value is true or false. I'd also add a bool that tells me whether I should even bother making a request--no sense in requesting if the last request came back empty (unless, perhaps, the data set could change since the last request). Either way, here's the code I'd start with:
( function( global )
{
var $ = global.jQuery,
$win = $( global ),
$doc = $( global.document ),
$ajaxLoader = $( 'div#ajaxloader' ),
$main = $( '#main' ),
requestInProgress = false,
outOfPosts = false;
$win.scroll( function()
{
if( ! requestInProgress &&
! outOfPosts &&
$win.scrollTop() === $doc.height() - $win.height()
)
{
requestInProgress = true;
$ajaxLoader.show();
$.ajax( {
url: 'loader.php',
data: {
lastid: $( '.container:last' ).attr( 'id' )
},
success: function( html )
{
if( html )
{
$main.append( html );
$ajaxLoader.hide();
}
else
{
outOfPosts = true;
$ajaxLoader.html( 'No more posts to show.' );
}
},
complete: function()
{
requestInProgress = false;
}
} );
}
} );
}( window ) );