Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load and remove pages of content based on scroll direction and height

I have simple data grid like so:

<div class="uiGridContent">
    <table>
        <tbody id="page-1">
             <tr>
                <td>Cell 1</td>
                <td>Cell 2</td>
                <td>Cell 3</td>
             </tr>
        </tbody>
    </table>
</div>

* Note that I have a header and footer in seperate tables in divs above and below the uiGridContent div. That are not required for this example.

var nextPage = 1, lastScrollTop = 0, st;

$('.uiGridContent').scroll(function(){

    var st = $(this).scrollTop();

    // We're scrolling down
    if (st > lastScrollTop){

        if( $('.uiGridContent').scrollTop() + $('.uiGridContent').innerHeight() >= $('.uiGridContent')[0].scrollHeight && nextPage < 10) {

            $.ajax({
                url: '<?php echo $appurl; ?>?page=' + nextPage,
                success: function(data) {
                    nextPage = nextPage + 1;
                    var content = $(data).find('.uiGrid tbody').html();

                    $('.uiGridContent tbody').last().after('<tbody id="page-'+nextPage+'">'+content+'</tbody>');

                },
                error: function(data) {

                    alert(data);

                }
            });

        }

        lastScrollTop = st;


    // We're scrolling up
    } else {

        if( $('.uiGridContent').scrollTop() + $('.uiGridContent').innerHeight() >= $('.uiGridContent tbody').last().height() ) {

            var pageToRemove = $('.uiGridContent tbody').last();

            if( pageToRemove.attr('id') != 'page-1') {
                pageToRemove.remove(); nextPage = nextPage - 1;

            } else {
                $('.uiGridContent').scrollTo(0,0);
            }

        }

        lastScrollTop = st;

    }

});

The idea being that as the user scrolls down the table, it will load in the next page when they reach the bottom of the last tbody in the gridcontent div. Which works fine!

The problem lies with the scrolling back up. Where the plan is to make it so that as the user scrolls back up past the last tbody it removes it again until they end up with just one remaining tbody (the original in this case). What actually happens is as soon as they start scrolling up it removes all of them except the first one, or sometimes misses the scroll up and takes the user to the top without removing all the other tbodys.

Any ideas? I think the problem lies with the if statement:

if( $('.uiGridContent').scrollTop() + $('.uiGridContent').innerHeight() >= $('.uiGridContent tbody').last().height() ) {

under the scroll up section.

like image 675
Cameron Avatar asked Nov 01 '22 12:11

Cameron


1 Answers

Yeah, you're right, the problem is that condition used in the if statement:

if ( $('.uiGridContent').scrollTop() + $('.uiGridContent').innerHeight() >= $('.uiGridContent tbody').last().height() )

This is asking whether or not the scrollTop of .uiGridContent plus it's .innerHeight() is greater than the height of the last tbody element. This is akin to asking if the bottom of the scrollable pane is below the height of the last tbody element if it were positioned at the top of .uiGridContent. That's not what you want.

What you want is to ask whether the bottom of the scrollable pane is above the top of the last tbody element. Since you only care about the last one, you can use:

if ( $('.uiGridContent').scrollTop() + $('.uiGridContent').innerHeight() <= ($this[0].scrollHeight - $('.uiGridContent tbody').last().height()) )

Although you really want to be caching those repeated calls to $( ... ) as I have in this demo:

http://jsfiddle.net/anmkU/3/

And you might want to cache the idea of a scrollBottom (the distance between the bottom of the content and the bottom of the viewable area) as you're using it regardless, and it probably helps the readability:

http://jsfiddle.net/anmkU/5/

like image 132
Ben Jackson Avatar answered Nov 09 '22 12:11

Ben Jackson