Reputation: 7333
Suppose I have 10 row in the table. Out of that only 5 will visible on the screen means when table loads then 1,2,3,4,5 rows are visible . When I scroll down with 1 row then row 2 , 3,4,5,6 are visible . Is there any way in Javascript or jquery to find which is the first row on the screen ? I have tried may ways like :
if(tr.position().top > $(table).position().top)
{
}
else
{
}
here I am comparing position of each row and with the table top position . But unfortunately every time I am getting the same position even I scrolled . how to do this ?
Upvotes: 1
Views: 3324
Reputation: 569
You can do something like this (using JQuery), on a scroll event callback, using a timeout to limit the frequency of the event, plus a cursor of the last found visible element, in way to perform a quicker search on next event. Here 'this' is the context of your view :
onScroll: function(e) {
if (this.scrollEvent) {
return;
}
this.scrollEvent = true;
setTimeout(function(view) {
// @replace you should check here is you view still exists using a status on your view context
if (view.isDestroyed) {
return;
}
view.scrollEvent = false;
var top = $('youselector on tbody').parent().parent().offset().top;
if (view.previousTopElement) {
if (view.previousTopElement.offset().top <= top) {
// the element is the previous, or on bottom of previous
var element = view.previousTopElement;
var i = view.previousTopElementIndex;
view.previousTopElement = null;
while (element.length) {
if (element.offset().top + element.height() >= top) {
// you can uses i + 1 for a 1 based position to display
view.previousTopElement = element;
view.previousTopElementIndex = i;
return;
}
element = element.next();
++i;
}
} else if (view.previousTopElement.offset().top > top) {
// the element is before the previous
var element = view.previousTopElement;
var i = view.previousTopElementIndex;
this.previousTopElement = null;
while (element.length) {
if (element.offset().top <= top) {
// you can uses i + 1 for a 1 based position to display
view.previousTopElement = element;
view.previousTopElementIndex = i;
return;
}
element = element.prev();
--i;
}
}
}
// no previous, get all rows
var rows = $('youselector on tbody').children('tr');
view.previousTopElement = null;
view.previousTopElementIndex = 0;
$.each(rows, function (i, el) {
var element = $(el);
if (element.offset().top + element.height() >= top) {
// you can uses i + 1 for a 1 based position to display
view.previousTopElement = element;
view.previousTopElementIndex = i;
return false;
}
});
}, 100, this); // you can adjust the timeout, pass your view context
}
This is the idea. In my case I do this optimisation because I can have many rows.
Upvotes: 0
Reputation: 6753
Using code from here with some modification:
JS Code (using div
in place of tr
):
$(function () {
$(window).scroll(function () {
var first = null; // element at the top
$("div").each(function(){ // check each div
// if it is visivle, and is there is not first element yet,
if( isScrolledIntoView($(this)) && !first) {
first = $(this); // this is the first
first.addClass("seen"); // visual aspect
}
// unnecessary, only for visual
else
$(this).removeClass("seen"); // remove class seen (visual)
});
});
// foreign code
function isScrolledIntoView(elem) {
// .....
}
});
DEMO
Scroll to see effect
Upvotes: 2