javascriptjquery

Add and Remove Class on Scroll Event


I am trying to add class or remove class on getting element top by using this demo. Here is the code as well:

$(document).ready(function () {
    var sec1_offset = $("#sec1").offset();
    var sec2_offset = $("#sec2").offset();
    var sec3_offset = $("#sec3").offset();
    var sec4_offset = $("#sec4").offset();
    var sec5_offset = $("#sec5").offset();
    var sec6_offset = $("#sec6").offset();
    var sec7_offset = $("#sec7").offset();
    $("section").scroll(function () {
       if (sec4_offset.top < 100) {
            alert("You Are in Sec 4");
       }
    });
});

I also change the $("section").scroll(function () { to $(body).scroll(function () { and $(document).scroll(function () { but it didn't work. What am I doing wrong?


Solution

  • You can listen to the scroll event of the window object, scroll event like the resize event is fired so many times, for efficiency you can throttle the handler, ie the handler is executed after a specified timeout.

    $(document).ready(function () {
        var $sec = $("section"),
            handle = null;
        var $w = $(window).scroll(function () {
            // clear the timeout handle
            clearTimeout(handle);
            // throttling the event handler
            handle = setTimeout(function() {
                var top = $w.scrollTop();
                // filtering the first matched element
                var $f = $sec.filter(function() {
                    return $(this).offset().top + $(this).height() >= top; 
                }).first().addClass('active');
    
                $sec.not($f).removeClass('active');
    
            }, 50); 
        }).scroll();
    });
    

    http://jsfiddle.net/UTCER/

    edit: If you want to add a class to another element, the most efficient way is using the index method:

    // Cache the object outside the `scroll` handler
    var $items = $('#menu li');
    
    // within the `setTimeout` context:
    var $f = $sec.filter(function() {
        return $(this).offset().top + $(this).height() >= top; 
    }).first();
    
    $items.removeClass('active').eq( $sec.index($f) ).addClass('active');