Loading content with ajax while scrolling

后端 未结 4 1783
温柔的废话
温柔的废话 2020-12-10 23:24

I\'m using jQuery Tools Plugin as image slider (image here), but due to large amount of images I need to load them few at a time. Since it\'s javascript coded, I can\'t have

相关标签:
4条回答
  • 2020-12-10 23:48

    First, you'll want to use jQuery for this

    Second, put a placeholder on your page to contain your data.

    <table id="dataTable" class="someClass" style="border-collapse: collapse;">
        <colgroup>
            <col width="12%" />
            <col width="12%" />
            <col width="12%" />
            <!-- Define your column widths -->
        </colgroup>
    </table>
    

    You'll need to code your own GetData method in a webservice, but this is the general idea (And call Refresh(); from your page load)

    function Refresh() {
        var getData = function(callback, context, startAt, batchSize) {
            MyWebservice.GetData(
                startAt,   //What record to start at (1 to start)
                batchSize, //Results per page
                3,         //Pages of data
                function(result, context, method) {
                    callback(result, context, method);
                },
                null,
                context
            );
        };
    
        $('#dataTable').scrolltable(getData);
    }
    

    The getData function variable is passed into the scrolltable plugin, it will be called as needed when the table is being scrolled. The callback and context are passed in, and used by the plugin to manage the object you are operating on (context) and the asynchronous nature of the web (callback)

    The GetData (note the case) webmethod needs to return a JSON object that contains some critical information, how your server side code does this is up to you, but the object this plugin expects is the following. The Prior and Post data are used to trigger when to load more data, basically, you can scroll through the middle/active page, but when you start seeing data in the prior or post page, we're going to need to fetch more data

        return new {
            // TotalRows in the ENTIRE result set (if it weren't paged/scrolled)
            TotalRows = tableElement.Element("ResultCount").Value,
            // The current position we are viewing at
            Position = startAt,
            // Number of items per "page"
            PageSize = tableElement.Element("PageSize").Value,
            // Number of pages we are working with (3)
            PageCount = tableElement.Element("PageCount").Value,
            // Data page prior to active results
            PriorData = tbodyTop.Html(),
            // Data to display as active results
            CurrentData = tbodyCtr.Html(),
            // Data to display after active results
            PostData = tbodyBot.Html()
        };
    

    Next is the plugin itself

    /// <reference path="../../js/jquery-1.2.6.js" />
    (function($) {
        $.fn.scrolltable = function(getDataFunction) {
            var setData = function(result, context) {
                var timeoutId = context.data('timeoutId');
                if (timeoutId) {
                    clearTimeout(timeoutId);
                    context.data('timeoutId', null);
                }
    
                var $table = context.find("table");
                var $topSpacer = $table.find('#topSpacer');
                var $bottomSpacer = $table.find('#bottomSpacer');
    
                var $newBodyT = $table.children('#bodyT');
                var $newBodyC = $table.children('#bodyC');
                var $newBodyB = $table.children('#bodyB');
    
                var preScrollTop = context[0].scrollTop;
    
                $newBodyT.html(result.PriorData);
                $newBodyC.html(result.CurrentData);
                $newBodyB.html(result.PostData);
    
                var rowHeight = $newBodyC.children('tr').height() || 20;
                var rowCountT = $newBodyT.children('tr').length;
                var rowCountC = $newBodyC.children('tr').length;
                var rowCountB = $newBodyB.children('tr').length;
    
                result.Position = parseInt(result.Position);
                $newBodyC.data('firstRow', result.Position);
                $newBodyC.data('lastRow', (result.Position + rowCountC));
                context.data('batchSize', result.PageSize);
                context.data('totalRows', result.TotalRows);
    
                var displayedRows = rowCountT + rowCountC + rowCountB;
                var rowCountTopSpacer = Math.max(result.Position - rowCountT - 1, 0);
                var rowCountBottomSpacer = result.TotalRows - displayedRows - rowCountTopSpacer;
    
                if (rowCountTopSpacer == 0) {
                    $topSpacer.closest('tbody').hide();
                } else {
                    $topSpacer.closest('tbody').show();
                    $topSpacer.height(Math.max(rowCountTopSpacer * rowHeight, 0));
                }
    
                if (rowCountBottomSpacer == 0) {
                    $bottomSpacer.closest('tbody').hide();
                } else {
                    $bottomSpacer.closest('tbody').show();
                    $bottomSpacer.height(Math.max(rowCountBottomSpacer * rowHeight, 0));
                }
    
                context[0].scrollTop = preScrollTop;  //Maintain Scroll Position as it sometimes was off
            };
    
            var onScroll = function(ev) {
                var $scrollContainer = $(ev.target);
    
                var $dataTable = $scrollContainer.find('#dataTable');
                var $bodyT = $dataTable.children('tbody#bodyT');
                var $bodyC = $dataTable.children('tbody#bodyC');
                var $bodyB = $dataTable.children('tbody#bodyB');
    
                var rowHeight = $bodyC.children('tr').height();
                var currentRow = Math.floor($scrollContainer.scrollTop() / rowHeight);
                var displayedRows = Math.floor($scrollContainer.height() / rowHeight);
    
                var batchSize = $scrollContainer.data('batchSize');
                var totalRows = $scrollContainer.data('totalRows');
    
                var prevRowCount = $bodyT.children('tr').length;
                var currRowCount = $bodyC.children('tr').length;
                var postRowCount = $bodyB.children('tr').length;
    
                var doGetData = (
                                    (
                                        (currentRow + displayedRows) < $bodyC.data('firstRow')                      //Scrolling up
                                        && (($bodyC.data('firstRow') - prevRowCount) > 1)                           // ...and data isn't already there
                                    )
                                ||
                                    (
                                        (currentRow > $bodyC.data('lastRow'))                                       //Scrolling down
                                        && (($bodyC.data('firstRow') + currRowCount + postRowCount) < totalRows)    // ...and data isn't already there
                                    )
                                );
    
                if (doGetData) {
                    var batchSize = $scrollContainer.data('batchSize');
    
                    var timeoutId = $scrollContainer.data('timeoutId');
                    if (timeoutId) {
                        clearTimeout(timeoutId);
                        $scrollContainer.data('timeoutId', null);
                    }
    
                    timeoutId = setTimeout(function() {
                        getDataFunction(setData, $scrollContainer, currentRow, batchSize);
                    }, 50);
    
                    $scrollContainer.data('timeoutId', timeoutId);
                }
            };
    
            return this.each(function() {
                var $dataTable = $(this);
    
                if (!getDataFunction) 
                    alert('GetDataFunction is Required');
    
                var batchSize = batchSize || 25;
                var outerContainerCss = outerContainerCss || {};
    
                var defaultContainerCss = {
                    overflow: 'auto',
                    width: '100%',
                    height: '200px',
                    position: 'relative'
                };
    
                var containerCss = $.extend({}, defaultContainerCss, outerContainerCss);
    
                if (! $dataTable.parent().hasClass('_outerContainer')) {
                    $dataTable
                        .wrap('<div class="_outerContainer" />')
                        .append($('<tbody class="spacer"><tr><td><div id="topSpacer" /></td></tr></tbody>'))
                        .append($('<tbody id="bodyT" />'))
                        .append($('<tbody id="bodyC" />'))
                        .append($('<tbody id="bodyB" />'))
                        .append($('<tbody class="spacer"><tr><td><div id="bottomSpacer" /></td></tr></tbody>'));
                }
    
                var $scrollContainer = $dataTable.parent();
    
                $scrollContainer
                    .css(containerCss)
                    .scroll(onScroll);
    
                getDataFunction(setData, $scrollContainer, 1, batchSize);
            });
        };
    })(jQuery);
    

    You'll likely need to tweak some things. I just converted it to a jQuery plugin and it's probably still a little glitchy.

    0 讨论(0)
  • 2020-12-10 23:58

    I just had to use jQuery Tools' API, the onSeek parameter within the scrollable() method.

    It was something like that

    $(".scrollable").scrollable({
        vertical: true,
        onSeek: function() {
            row = this.getIndex();
            // Check if it's worth to load more content
            if(row%4 == 0 && row != 0) {
                var id = this.getItems().find('img').filter(':last').attr('id');
                id = parseInt(id);
                $.get('galeria.items.php?id='+id, null, function(html) {
                    $('.items').append(html);
                });
            }
        }
    }); 
    
    0 讨论(0)
  • 2020-12-11 00:05

    try something like this

    $('#scrollable').find('img:last').load(function() {
            //load the content  
    });
    

    OR find the offset location/position of the last image and try loading your content when you reach the offset position on scrolling

    HTML :

    <div>
       <br><br><br><br><br><br><br><br><br><br><br><br><br><br>
       <br><br><br><br><br><br><br><br><br><br><br><br><br><br>
       <span>Hello !!</span>
       <br><br><br><br><br><br><br><br><br><br><br><br><br><br>
       <br><br><br><br><br><br><br><br><br><br><br><br><br><br>
    </div> 
    

    some CSS :

    div {
        width:200px;
        height:200px;
        overflow:scroll;
    }
    

    Javascript :

    $(document).ready(function() {
         $('div').scroll(function() {
             var pos    = $('div').scrollTop();
             var offset = $('span').offset().top;
             if(pos >= offset ) {
               alert('you have reached your destiny');
             }
       });
    });    
    

    here's a quick demo http://jsfiddle.net/8QbwU/

    Though Demo doesn't met your full requirements, I believe It does give you some light to proceed further :)

    0 讨论(0)
  • 2020-12-11 00:08

    That could be made the following way:

    //When the DOM is ready...
    $(document).ready(function() {
    
       //When the user scrolls...
       $(window).scroll(function() {
           var tolerance = 800,
               scrollTop = $(window).scrollTop();
    
           //If the the distance to the top is greater than the tolerance...
           if(scrollTop > tolerance) {
    
               //Do something. Ajax Call, Animations, whatever.
    
           }
       }) ;
    });
    

    That should do the trick.

    EDIT: Because you're not using the native scroll, we've got to do a little fix to the code:

    //When the DOM is ready...
    $(document).ready(function() {
    
       //When the user scrolls...
       $("div.scrollable").find(".next").click(function() {
           var tolerance = 800,
               // The absolute value of the integer associated 
               // to the top css property
               scrollTop = Math.abs(parseInt($("div.items").css("top")));
    
           //If the the distance to the top is greater than the tolerance...
           if(scrollTop > tolerance) {
    
               //Do something. Ajax Call, Animations, whatever.
    
           }
       }) ;
    });
    
    0 讨论(0)
提交回复
热议问题