views:

493

answers:

4

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!

A: 

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

Ninja Dude
The problem is that it's using the OS scrolling and my script doesn't use it, it uses a jquery plugin. Check my script, try to use it there [http://jsfiddle.net/PxGTJ/](http://jsfiddle.net/PxGTJ/)
Rodrigo Alves
what actually `OS scrolling` means ? I don't understand
Ninja Dude
I don't know exactly, I tried to say that your scrolling isn't the one I'm using which is javascript. This way, your script doesn't work for me, 'cause it can't get scroll properties
Rodrigo Alves
ok whatever, I just wanna give you some basic Idea !! Have a Nice Day Rodrigo !!
Ninja Dude
+1  A: 

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.

       }
   }) ;
});
Rodolfo Palma
What you mean by `window`? Should I change it for the name of my div? Or is it the word window?
Rodrigo Alves
`window` is a dom object it's not a name it represents an open window in your browse (source : http://www.w3schools.com/jsref/obj_window.asp )
Ninja Dude
But it's not the window I'm scrolling it's only a div with javascript "pseudo-scroll". Have you guys tried to click in next or prev button to see what happen?
Rodrigo Alves
Didn't notice that when I was writing the answer :P I'll edit the answer.
Rodolfo Palma
Why can't I even `alert()` the scrollTop variable? Check it out: [http://jsfiddle.net/PxGTJ/1/](http://jsfiddle.net/PxGTJ/1/)
Rodrigo Alves
When I write `alert(Math.abs(parseInt($(this).css("top"))));` inside there it prints `NaN` :(
Rodrigo Alves
Try the code now.
Rodolfo Palma
A: 

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.

Chad
A: 

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