简体   繁体   中英

Stop infinite scroll from jumping to end of page when loading content

I have implemented infinite scroll with isotope on my website and I am having a problem with loading posts. The posts load fine, but lets say I scroll down to load more posts but I am still viewing the posts already there, infinite scroll jumps to the bottom of the page whenever new posts are loaded. How can I stop this behavior and maintain the position on the page even when more posts are loaded?

My script --

$(function () {
        var selectChoice, updatePageState, updateFiltersFromObject,
            $container = $('.isotope');
        ////////////////////////////////////////////////////////////////////////////////////
        /// EVENT HANDLERS
        ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        // Mark filtering element as active/inactive and trigger filters update
        $('.js-filter').on( 'click', '[data-filter]', function (event) {
          event.preventDefault();
          selectChoice($(this), {click: true});
          $container.trigger('filter-update');
        });
        //////////////////////////////////////////////////////
        // Sort filtered (or not) elements
        $('.js-sort').on('click', '[data-sort]', function (event) {
          event.preventDefault();
          selectChoice($(this), {click: true});
          $container.trigger('filter-update');
        });
        //////////////////////////////////////////////////////
        // Listen to filters update event and update Isotope filters based on the marked elements
        $container.on('filter-update', function (event, opts) {
          var filters, sorting, push;
          opts = opts || {};
          filters = $('.js-filter li.active a:not([data-filter="all"])').map(function () {
            return $(this).data('filter');
          }).toArray();
          sorting = $('.js-sort li.active a').map(function () {
            return $(this).data('sort');
          }).toArray();
          if (typeof opts.pushState == 'undefined' || opts.pushState) {
            updatePageState(filters, sorting);
          }
          $container.isotope({
            filter: filters.join(''),
            sortBy: sorting
          });

        });
        //////////////////////////////////////////////////////
        // Set a handler for history state change
        History.Adapter.bind(window, 'statechange', function () {
          var state = History.getState();
          updateFiltersFromObject(state.data);
          $container.trigger('filter-update', {pushState: false});
        });
        ////////////////////////////////////////////////////////////////////////////////////
        /// HELPERS FUNCTIONS
        ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        // Build an URI to get the query string to update the page history state
        updatePageState = function (filters, sorting) {
          var uri = new URI('');
          $.each(filters, function (idx, filter) {
            var match = /^\.([^-]+)-(.*)$/.exec(filter);
            if (match && match.length == 3) {
              uri.addSearch(match[1], match[2]);
            }
          });
          $.each(sorting, function (idx, sort) {
            uri.addSearch('sort', sort);
          });
          History.pushState(uri.search(true), null, uri.search() || '?');
        };
        //////////////////////////////////////////////////////
        // Select the clicked (or from URL) choice in the dropdown menu
        selectChoice = function ($link, opts) {
          var $group = $link.closest('.btn-group'),
              $li = $link.closest('li'),
              mediumFilter = $group.length == 0;
          if (mediumFilter) {
            $group = $link.closest('.js-filter');
          }

          if (opts.click) {
            $li.toggleClass('active');
          } else {
            $li.addClass('active');
          }
          $group.find('.active').not($li).removeClass('active');
          if (!mediumFilter) {
            if ($group.find('li.active').length == 0) {
              $group.find('li:first-child').addClass('active');
            }
            $group.find('.selection').html($group.find('li.active a').first().html());
          }
        };
        //////////////////////////////////////////////////////
        // Update filters by the values in the current URL
        updateFiltersFromObject = function (values) {
          if ($.isEmptyObject(values)) {
            $('.js-filter').each(function () {
                selectChoice($(this).find('li').first(), {click: false});
            });
            selectChoice($('.js-sort').find('li').first(), {click: false});
          } else {
            $.each(values, function (key, val) {
              val = typeof val == 'string' ? [val] : val;
              $.each(val, function (idx, v) {
                var $filter = $('[data-filter=".' + key + '-' + v + '"]'),
                    $sort = $('[data-sort="' + v + '"]');
                if ($filter.length > 0) {
                  selectChoice($filter, {click: false});
                } else if ($sort.length > 0) {
                  selectChoice($sort, {click: false});
                }
              });
            });
          }
        };
        ////////////////////////////////////////////////////////////////////////////////////
        /// Initialization
        ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        // Initialize Isotope
$container.imagesLoaded( function(){
        $container.isotope({
  masonry: { resizesContainer: true },
          itemSelector: '.item',
          getSortData: {
 date: function ( itemElem ) {
      var date = $( itemElem ).find('.thedate').text();
      return parseInt( date.replace( /[\(\)]/g, '') );
    },
area: function( itemElem ) { // function
      var area = $( itemElem ).find('.thearea').text();
      return parseInt( area.replace( /[\(\)]/g, '') );
    },
price: function( itemElem ) { // function
      var price = $( itemElem ).find('.theprice').text();
      return parseInt( price.replace( /[\(\)]/g, '') );
    }
          }
        });

var total = $(".next a:last").html();
var pgCount = 1;
var numPg = total;

    // jQuery InfiniteScroll Plugin.
    $container.infinitescroll({
 contentSelector  : '.isotope',
 speed : 'fast',
behavior: 'simplyrecipes',
         navSelector  : '#pagi',    // selector for the paged navigation 
        nextSelector : '#pagi a.next',  // selector for the NEXT link (to page 2)
        itemSelector : '.item',     // selector for all items you'll retrieve
        animate: true,
debug: true,
        loading: {
selector: '#infscr-loading',
            finishedMsg: 'No more content to load.'
        }
    },
    // Trigger Masonry as a callback.
    function( newElements ) {
        pgCount++;

        if(pgCount == numPg) {
            $(window).unbind('.infscr');
            $container.isotope('reload');
            $container.append( newElements ).isotope( 'appended', newElements, true );
            $('#infscr-loading').find('em').text('No more content to load.');
            $('#infscr-loading').animate({
                opacity: 1
            }, 200);
            setTimeout(function() {
                $('#infscr-loading').animate({
                    opacity: 0
                }, 300);
            });
        } else {
            loadPosts(newElements);
        }
    }); 
});

function loadPosts(newElements) {
    // Hide new posts while they are still loading.
    var newElems = $( newElements ).css({ opacity: 0 });
    // Ensure that images load before adding to masonry layout.
    newElems.imagesLoaded(function() {
        // Show new elements now that they're loaded.
        newElems.animate({ opacity: 1 });
        $container.isotope( 'appended', newElems, true );      
    });
}
        //////////////////////////////////////////////////////
        // Initialize counters
        $('.stat-count').each(function () {
          var $count = $(this),
              filter = $count.closest('[data-filter]').data('filter');
          $count.html($(filter).length);
        });
        //////////////////////////////////////////////////////
        // Set initial filters from URL
        updateFiltersFromObject(new URI().search(true));
        $container.trigger('filter-update', {pushState: false});
      }); 
});

You can start by overriding the default animate property of infinite-scroll

$container.infinitescroll({
    animate:false, //this does just that
});

And about your dublicate entry for every request (or perhaps some requests ), It has something to do with your backend ie the way you are offseting the data

Infinite Scroll works great with page numbers ie it Sends 2,3,4,5,6 ... So For every request its sends that request.

I think you are using page offset instead , and you will probably end up with duplicate entries .

If you are using php as your receiving end ... this might help

//In your Controller
$temp = ( $page_offset * $per_page );
$offset = $temp - $per_page ;

//In your model
$this->db->query("SELECT * FROM GALLERY OFFSET $offset limit 10");

This is just a rough idea , I hope it helps.

If it does , Care to Check out Sticky Bubble ? - A game available for free on Google Play .

Cheers :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM