How is the endless scrolling done? I know that through AJAX, but how does it indicate from what for which post it is necessary to pull it out, etc.

    3 answers 3

    Well, in general, people transmit the page number, via POST, or GET it does not matter, they just remember which page is currently open and do ++ when they reach the bottom with a scroller.

    • and if without pages to do? - Zow
    • here apparently there is a view that the theoretical output is transferred to the javascript and when the bottom of the page is reached, a request is sent <current quantity> + <next packet> - thunder

    This is called the Cursor Pagination.

    Example:
    You have a server and a database in which there are 100 posts. The server gives 10 posts per page. Numbered pagination makes a request to the server and in the request we pass the page number for which we want to get 10 posts. In the cursor pagination, everything is exactly the same, only we transfer not any page in the request, but one after the other:

    1. In the client application, you should have a list of posts: postsList and current page number: currentPage .
    2. When loading the page, a request is made for a dozen posts. When we got the answer with the posts, we put them in the postsList and memorize the page currentPage = 1 .
    3. We catch the event that the user has scrolled the list to the last post and make a request to receive a dozen posts from the currentPage + 1 page.
    4. We expand the postsList data (add to the end of the list). Remember the page: currentPage=2 .

    That's all. Items 3 and 4 are executed until all 100 posts are loaded.

    • one
      I note that instead of currentPage may be better to use something like lastPostId with a query to the where id < lastPostId type database where id < lastPostId , (or a similar variant with the date of publication), so duplicates are excluded (if a new post appears between the requests) less - andreymal
    • @andreymal One could make a similar request, but it would not be enough to specify id < lastPostId . You are programming in Python . Django ? Just why reinvent the wheel when there are already ready-made solutions. Using the Django REST framework with a simple request with the page number in the parameters, you can get the necessary data: https://my_host/posts/?page=123 - Max
    • Then, that the proposed bike is simpler and more efficient, of course. Query to database with offset (page-1)*count, count is not the best solution for infinite scrolling. - andreymal
    • Give a detailed answer to this question with your decision. This is not a discussion forum. - Max
    • one
      I do not want, it is similar to yours, only lastPostId instead of currentPage :) - andreymal

    An example implementation with detailed comments:

     /* * На сколько страниц автоматичСски ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‡ΠΈΠ²Π°Π΅ΠΌ Π΄ΠΎ остановки */ var maxPages = 3; /* * Π—Π° сколько Π΄ΠΎ ΠΊΠΎΠ½Ρ†Π° страницы Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΡƒ */ var scrollBufferRatio = 1 / 3; /* * Π“Π΄Π΅ находится ΠΎΠ±Π»Π°ΡΡ‚ΡŒ для дополнСния (содСрТимоС) */ var elementContainerSelector = '.messages'; /* * Π§Ρ‚ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ Ссли Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½ Π½ΠΎΠ²ΠΎΠ΅ содСрТимоС */ var elementFindingErrorHandler = function() { throw "Could not find " + elementContainerSelector; }; /* * Названия события ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ * Ссли Π΅ΡΡ‚ΡŒ нСсколько областСй ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ */ var eventName = 'scroll.toInfinity'; /* * Π“Π΄Π΅ находится Π²Ρ‹Π±ΠΎΡ€ страниц для ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° */ var pagerSelector = '.pager'; /* * Π“Π΄Π΅ Π½Π°ΠΉΡ‚ΠΈ ссылку Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ страницу */ var nextPageSelector = '.pager .nextpage'; var $window = $(window); // ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ страницы var $elementContainer; var topOffset = 0, scrollBuffer = 1, pageCounter = 1; var eventProcessor = function(finished) { // позиция ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ ΠΊΠΎΠ³Π΄Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΡΡ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° // считаСтся ΠΎΡ‚ фактичСской высоты содСрТимого var triggerPosition = $elementContainer.height() + topOffset - scrollBuffer; // тСкущая позиция ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ ΠΏΠΎ Π½ΠΈΠΆΠ½Π΅ΠΉ части ΠΎΠΊΠ½Π° var scrollPosition = $window.scrollTop() + $window.height(); // Π΅Ρ‰Π΅ Π½Π΅ дошли Π΄ΠΎ Π½ΡƒΠΆΠ½ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠΈ, Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ if (scrollPosition < triggerPosition) { // Π½ΠΎ ΠΆΠ΄Ρ‘ΠΌ дальшС finished(); return true; } // пролистали достаточноС число страниц if (pageCounter >= maxPages) { // Π΄Π°Π΄ΠΈΠΌ Π²Ρ‹Π±ΠΎΡ€ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ Π»ΠΈΡΡ‚Π°Ρ‚ΡŒ Π»ΠΈ дальшС $(pagerSelector).show(); // Π½Π΅ пСрСзапускаСм Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ return true; } // Ссли ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ страницы Π½Π΅Ρ‚... var $nextPage = $(nextPageSelector); if ($nextPage.length == 0) { // Ρ‚ΠΎ ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ дальшС Π½Π΅Ρ‡Π΅Π³ΠΎ return true; } $.get($nextPage.attr('href'), function(data) { var $data = $(data); // Π½Π°ΠΉΠ΄Π΅ΠΌ содСрТимоС Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ страницС var $newContent = $data.find(elementContainerSelector); if ($newContent.length == 0) { // Ссли элСмСнт Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½, ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΡ€Π½Π΅Π²Ρ‹ΠΌ $newContent = $data.filter(elementContainerSelector); } // Ссли Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½ΠΎ, Ρ‚ΠΎ это ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎ ошибка if ($newContent.length == 0) { elementFindingErrorHandler(); } // содСрТимоС ΠΈΠ· ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ страницы допишСм // ΠΊ содСрТимому страницы Π² ΠΎΠΊΠ½Π΅ $elementContainer.append($newContent.first().html()); // Π½Π°ΠΉΠ΄Π΅ΠΌ Π²Ρ‹Π±ΠΎΡ€ страниц Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ страницС var $newPager = $data.find(pagerSelector); if ($newPager.length == 0) { // ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΉ элСмСнт Ρ‚ΠΎΠΆΠ΅ ΠΏΠΎΠΈΡ‰Π΅ΠΌ $newPager = $data.filter(pagerSelector); } // Π·Π°ΠΌΠ΅Π½ΠΈΠΌ Π²Ρ‹Π±ΠΎΡ€ страниц Π½ΠΎΠ²Ρ‹ΠΌ var newPager = $newPager.first().html(); // ΠΈ скроСм Π΅Π³ΠΎ ΠΏΠΎΠΊΠ° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π½ΡƒΠΆΠ΅Π½ $(pagerSelector).html(newPager).hide(); }).always(function() { pageCounter += 1; // ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ снова слСдим Π·Π° ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΎΠΉ finished(); }); }; var eventTimeout = 0; var eventHandler = function() { // событиС Π½Π° ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΡƒ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΡ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· $window.unbind(eventName); clearTimeout(eventTimeout); eventTimeout = setTimeout(function() { // возьмСм Π½Π΅Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ ΠΏΠ°ΡƒΠ·Ρƒ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΡΡ‚Π°Π²ΡˆΠΈΠ΅ΡΡ // пиксСли ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ событии ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ eventProcessor(function() { // послС окончания Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ снова ΠΆΠ΄Π΅ΠΌ ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ $window.bind(eventName, eventHandler); }); }, 100); }; $(function() { $elementContainer = $(elementContainerSelector); // расстояния Π΄ΠΎ элСмСнта ΠΎΡ‚ Π²Π΅Ρ€Ρ…Π° экрана topOffset = $elementContainer.offset().top; // Π·Π°Π΄Π°Π΄ΠΈΠΌ ΠΏΡ€ΠΎΠΏΠΎΡ€Ρ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ высотС scrollBuffer = $elementContainer.height() * scrollBufferRatio; $window.bind(eventName, eventHandler); }); 

    All this is better to call in the closure so as not to litter in the window .

    Taken from here , MIT license .