Search code examples
jqueryjquery-pluginsjquery-pagination

Can't stop scroll event from firing too many times


So I have been reading up on this problem and have seen quite a lot of different solutions. At the moment my code looks like this:

I am using this plugin: http://benalman.com/projects/jquery-throttle-debounce-plugin/

// Bind throttled scroll event to load new items when page is scrolled to the bottom.
$(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad));

Olemas.ScrollLoad = function()  {
  if ($(window).data('loading') == true) return;
  if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
      if (Olemas.NextPage <= Olemas.MaxPage) {
          $(window).unbind('scroll'); // I have tried unbinding the event to stop it from launching
          Olemas.LoadMoreItems(Olemas.DivToUpdate); // load the new items
          $(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad)); // rebind scroll event.
      }

  }
};

The problem is that even though the event is firing once every 800 ms. When I scroll to the bottom fast, the scroll event is firing too many times and the pages are loaded all wrong.

if ($(window).scrollTop() >= ($(document).height() - $(window).height()))

This statement should not pass after my items are loaded to the page, but it still passes a few times before it realizes the page height has changed. Is it possible that the height attributes are not updated quickly enough or the scroll events are already loaded into the DOM somehow?

What can I do to stop the scroll event from firing after the LoadMoreItems function has expanded the page.

EDIT.

So in this function, the alerts are ran 2 times and then an alert in the LoadMoreItems ajax success.

Olemas.ScrollLoad = function()  {
/// <summary>
/// Loads more items when scrolled to the bottom.
/// </summary>
if ($(window).data('loading') == true) return;
if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
    if (Olemas.NextPage <= Olemas.MaxPage) {
        alert(Olemas.NextPage); // This runs 2 times, before the LoadMoreItems changes the NextPage value
        $(window).off('scroll', $.throttle(800, Olemas.ScrollLoad));

        Olemas.LoadMoreItems(Olemas.DivToUpdate);
        $(window).data('loading', false).on('scroll', $.throttle(800, Olemas.ScrollLoad)); // rebind scroll event.
    }

}
};

Olemas.LoadMoreItems = function () {
  $(window).data('loading', true);
  $.ajax({
      url: Olemas.ActionLink,
      data: { "page": Olemas.NextPage, "facId": Olemas.FacultyId },
      success: function (data) {
          $(".loadingImage").hide();
          $(data).appendTo(Olemas.DivToUpdate);
          alert("Done") // This is run after the previous alerts have fired 2 times.
          Olemas.NextPage++;
          Olemas.CheckPages();
      }
  });
  return false;

};

Solution

  • Okay so my problem was the following:

    // Bind throttled scroll event to load new items when page is scrolled to the bottom.
    $(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad));
    
    Olemas.ScrollLoad = function()  {
      if ($(window).data('loading') == true) return;
      if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
       if (Olemas.NextPage <= Olemas.MaxPage) {
          $(window).unbind('scroll'); // I have tried unbinding the event to stop it from launching
          Olemas.LoadMoreItems(Olemas.DivToUpdate); // load the new items
          $(window).data('loading', false).scroll($.throttle(800, Olemas.ScrollLoad)); // rebind scroll event.
          //The LoadMoreItems was an AJAX method and the rebinding was made before the ajax call had succeeded. 
          //That is why it fired the scroll event too many times.
      }
    
    }
    };
    

    I solved it, by moving the loading boolean check into the LoadMoreItems method, that way the method had to finish before the scroll was rebinded.