开发者

Loading content with ajax while scrolling

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 the scroll position as far as I know. I want to load them as soon as the last image shows up or something like that. I have no idea where I put and event listener neither anything.

Here is my code http://jsfiddle.net/PxGTJ/

Give me some light, please!


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);
            });
        }
    }
}); 


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.

       }
   }) ;
});


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 :)


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜