0

I'm trying to adapt this code from Stackoverflow for my specific needs. I need to highlight via addClass the first <li> that is completely visible in a scrolling <ol> viewport, regardless of length of <li>. I swapped the $(window) scrolling part of the code for a scrollable <ol> which nearly does the job but results in offset issues after exceeding an <li> length because the <li> are smaller in height than the parent <ol> height :

function testInView($el){
    var wTop = $('#OL').scrollTop() / 6; // Updated
    var wBot = wTop + $('#OL').height();
    var eTop = $el.offset().top;
    var eBot = eTop + $el.height();
    return ((eBot <= wBot) && (eTop >= wTop));
}
function setInView(){
    $("li").each(function(){
        var $zis = $(this);
        $zis.removeClass("inview");
        if(testInView($zis)){
           $zis.addClass("inview");
        }
    });
$('#OL').find('.inview:first').next().next().addClass(".higlight"); // Updated
}

$('#OL').scroll(function(){
    setInView();
});

My <ol> makes visible six <li> of 80px each in height when scrolling, therefore my <ol> is 480px in height. How can the above code be edited to work with these heights regardless of amount of <li> length, or better yet, can the code be written to dynamically adapt to any <li> and/or <ol> heights?

UPDATE 1

I amended the above code (see comments) :

var wTop = $('#OL').scrollTop() / 6; // Added devide by 6

...

$('#OL').find('.inview:first').next().next().addClass(".higlight");
// Added two next()

The above edits enable highlighting in a more stable manner the <li> targets, however, as <li> length grows, .highlight targets the bottom-most <li> and does not apply at all when <li> length exceeds 38. The edits act more like a hack than a solid solution, any hints on cleaner efficient code?

Community
  • 1
  • 1
koolness
  • 166
  • 19

1 Answers1

0

UPDATE 2 - FINAL

This Stackoverflow link provides "cleaner efficient code" that I modified for use as basis of answer for my above question :

function setInView(){

var scroll = $('ol:visible').scrollTop() / 1000; // See Note below
var elements = $('ol:visible').find('li');
var el;

   for (var i=0; i<elements.length; i++) {
    elements.css('border-color',''); // Erase color with css
        el = $(elements[i]);
        if (el.offset().top >= scroll && el.is(':visible')){
            // "el" is the first visible element here!
            // Do something fancy with it
            el.next().next().css('border-color','#F00');
            // Quit the loop
            break;
        }
    }
}

$('ol').scroll(function(){
setInView();
});

Note: <ol> visibility selector ensures this function only targets scrollable ordered lists that are made visible. Dividing by 1000+ ensures lists of <li> length of 600+ will be targeted correctly by the function. I used css color swaps as they were faster to handle than classes for my application.

Community
  • 1
  • 1
koolness
  • 166
  • 19