How to prevent multiple AJAX calls when using the jQuery scroll event handler during lazy loading?

I am loading data into my DIV using AJAX using 3 different functions. I am trying to prevent multiple AJAX calls when the browser scroller stays at the bottom of the DIV that I am lazily loading data.

This works, but sometimes (sometimes) the scroller stays at the bottom of my div and this will cause a lot of AJAX calls. How to prevent this?

$(document).ready(function() { //form submit by click $("#submit").click(function(e) { // Prevent Default Action In Case to Load data by form e.preventDefault(); //prevent select to post empty data $('select').each(function() { if ($(this).val() == '') { $(this).attr('disabled', 'disabled'); } }); // Define what we need var loading = "<img src='/zojfa/images/loading.gif' alt='Loading...' />"; var scrolltop = $('#scrollbox').attr('scrollTop'); var scrollheight = $('#scrollbox').attr('scrollHeight'); var windowheight = $('#scrollbox').attr('clientHeight'); var post = $(this).attr("name") + "=" + $(this).val(); var form_data = $('#search_form').serialize() + "&" + post; var scrolloffset = 20; //empty content if another value sent to code $('#content').empty(); //load data loaddata(form_data, 0); }); //listen to scroll function $('#scrollbox').scroll(function() { //define what we need var scrolltop = $('#scrollbox').attr('scrollTop'); var scrollheight = $('#scrollbox').attr('scrollHeight'); var windowheight = $('#scrollbox').attr('clientHeight'); var scrolloffset = 20; //get number of div which will append to script in case of limit database to page 2 or 3 or... size = $('#content > div').children().size(); //if we reach to bottom of div we are going to call to ajax function if (scrolltop >= (scrollheight - (windowheight + scrolloffset))) { var form_data = $('#formdata').val(); //if remain of size(count of div) is 0 then we have more data to show because we limit data provided by script to 7 field(we handle situation that we had 14 or 21 respond from database in "next step" because if there is no data to show we dont have to let script to run) if (size % 7 == 0) { //call to load data function setTimeout(function() { loaddata(form_data, size) }, 1500); } else { //do nothing its just in case we need to append something like no more data to load } } }); // page load finish }); //function to load data function loaddata(form_data, size) { number = "&size=" + size; //fetch new items $.post('dosearch.php', form_data + number, function(newitems) { //next step : if page echoing "" then do nothing if (newitems == '') {} else { //if we have data append these data to our div #content $('#content').append(newitems); } }); }​ 

Update

I also loved @Kent Pawar and dear @EJ Brennan , but now I get more AJAX calls when I get to the bottom of the div and it still doesn't work.

 $("#submit").click(function(e) { // Do some Default e.preventDefault(); $('select').each(function() { if ($(this).val() == '') { $(this).attr('disabled', 'disabled'); } }); // var what we need var loading = "<img src='/zojfa/images/loading.gif' alt='Loading...' />"; var scrolltop = $('#scrollbox').attr('scrollTop'); var scrollheight = $('#scrollbox').attr('scrollHeight'); var windowheight = $('#scrollbox').attr('clientHeight'); var post = $(this).attr("name") + "=" + $(this).val(); var form_data = $('#search_form').serialize() + "&" + post; var scrolloffset = 20; $('#content').empty(); //load data loaddata(form_data, 0); $('select').each(function() { if ($(this).val() == '') { $(this).removeAttr('disabled'); } }); }); $('#scrollbox').scroll(function() { //var what we need var scrolltop = $('#scrollbox').attr('scrollTop'); var scrollheight = $('#scrollbox').attr('scrollHeight'); var windowheight = $('#scrollbox').attr('clientHeight'); var scrolloffset = 20; // when we reach size = $('#content > div').children().size(); if ($('#scrollbox').data('ajaxready') === false) return; if (scrolltop >= (scrollheight - (windowheight + scrolloffset))) { $('#scrollbox').data('ajaxready', false); var form_data = $('#formdata').val(); if (size % 7 == 0) { setTimeout(function() { loaddata(form_data, size) }, 1500); } else { } } $('#scrollbox').data('ajaxready', true); // page load finish }); function loaddata(form_data, size) { number = "&size=" + size; //fetch new items $.post('dosearch.php', form_data + number, function(newitems) { if (newitems == '') {} else { $('#content').append(newitems); } }); } 
+4
source share
2 answers

Well, the problem is not that the scroller is at the bottom of the page, but with the way the event handler works. Sometimes the scroller will be at the bottom of the page, for example, say when there are no more messages to download ... for example, watch Facebook.

Currently, the jQuery scroll event is fired when a scroll occurs.

JQuery docs:

A scroll event is dispatched whenever a scroll position of an element changes, regardless of the reason. Clicking or dragging the scroll bar, dragging inside an element, pressing the arrow keys, or using the mouse scroll wheel can trigger this event.

Now your task for your script is to make one AJAX call to check if there is content to download. You need to modify your script to stop several AJAX calls during this time, and as I can see, @EJ Brennan has already suggested the same :).

You can add flags as follows:

 //listen to scroll function $('#scrollbox').scroll(function(){ //[Kent] Before we service the event, we check if the last scroll event was handled/completed. //If it is not yet compelted, don't start another one and jump out of the code. if ($(window).data('ajax_in_progress') === true) return; //define what we need var scrolltop=$('#scrollbox').attr('scrollTop'); var scrollheight=$('#scrollbox').attr('scrollHeight'); var windowheight=$('#scrollbox').attr('clientHeight'); var scrolloffset=20; //get number of div which will append to script in case of limit database to page 2 or 3 or... size = $('#content > div').children().size(); //if we reach to bottom of div we are going to call to ajax function if(scrolltop>=(scrollheight-(windowheight+scrolloffset))){ $(window).data('ajax_in_progress', true); //[Kent] prevent more scroll events as AJAX request will soon begin. var form_data = $('#formdata').val(); // if remain of size(count of div) is 0 then we have more data to show because // we limit data provided by script to 7 field(we handle situation that we had // 14 or 21 respond from database in "next step" because if there is no data to // show we dont have to let script to run) if(size % 7 == 0){ //call to load data function setTimeout(function(){loaddata(form_data, size)}, 1500); }else{ //do nothing its just in case we need to append something like no more data to load } } }); //function to load data function loaddata(form_data, size){ number = "&size=" + size; //fetch new items $.post('dosearch.php', form_data+number, function(newitems){ // [Kent] This is the callback funciton that gets executed ONLY // when the AJAX request has completed. We will append the data // into the DOM and then reset the FLAG. //next step : if page echoing "" then do nothing if(newitems == ''){ }else{ //if we have data append these data to our div #content $('#content').append(newitems).each(function() { //Adding a callback to append. // So we reset the flags here to indicate the scroll event // has been handled/completed and so we turn scrolling events back on $(window).data('ajax_in_progress', false); }); } }); } 
+5
source

Not 100% clarity on your specific problem, but I also had similar problems with firefox that fired a lot of scroll events before the first was completed, while chrome didn't.

What I did was add a flag when I started loading new data (from ajax) and cancel the flag when it was completed, and this solved my problem.

Something like that:

  $(window).scroll(function () { //if last scroll is not done, don't start another one. if ($(window).data('ajaxready') === false) return; if ($(window).scrollTop() >= $(document).height() - $(window).height() - 100) { $(window).data('ajaxready', false); //prevent more scroll events YourFunctionCallToGetGetMoreData(); //go get the data here. } //turn scrolling events back on $(window).data('ajaxready', true); }); 

in your case, the call to enable backward scrolling is included in the ajax data load callback function.

+3
source

All Articles