Liam
Liam

Reputation: 9855

When element appears in the viewport run function

I'm trying to write a function so that when my element comes into view a function is attached to it.

I have a range of elements on my page, element1, element2, element3 and I'd like to write a function that checks when either of these is in the viewport, rather than having a big if statement.

I have the following only this doesn't seem to work, and nothing happens?

var $findme = $('.section').each();

function Scrolled() {
    var findmeOffset = $findme.offset(),
        findmeTop = findmeOffset.top,
        scrollTop = $(document).scrollTop(),
        visibleBottom = window.innerHeight;

    if (findmeTop < scrollTop + visibleBottom) {
        console.log('element is visible');
    }

}

function Setup() {
    var $top = $('#top'),
        $bottom = $('#bottom');

    $top.height(500);
    $bottom.height(500);

    $(window).scroll(function() {
        Scrolled();
    });
}

$(document).ready(function() {
    Setup();

});

DEMO

http://jsfiddle.net/Yh7x3/

Upvotes: 2

Views: 1502

Answers (2)

Oscar Paz
Oscar Paz

Reputation: 18302

Here is a woking solution: jsfiddle.

Your main problem is that you were using $fimdme in you scroll event handler, what caused that it only applied to the first element. Calling .each() to an element with no arguments has no effect at all.

Here's the new code. I modified it so, every time you scroll, the alert shows the text of a section if, and only if, it is visible now (in the viewport) and was not visible before, whether you scroll down or you scroll up.

var $findme = $('.section');

function Scrolled() {
    $findme.each(function() {
        var $section = $(this),
            findmeOffset = $section.offset(),
            findmeTop = findmeOffset.top,
            findmeBottom = $section.height() + findmeTop,
            scrollTop = $(document).scrollTop(),
            visibleBottom = window.innerHeight,
            prevVisible = $section.prop('_visible');

        if ((findmeTop > scrollTop + visibleBottom) ||
             findmeBottom < scrollTop) {
            visible = false;
        } else visible = true;

        if (!prevVisible && visible) {
            alert($section.text());
        }
        $section.prop('_visible', visible);
    });

}

function Setup() {
    var $top = $('#top'),
        $bottom = $('#bottom');

    $top.height(500);
    $bottom.height(500);

    $(window).scroll(function() {
        Scrolled();
    });
}

$(document).ready(function() {
    Setup();
});

Upvotes: 3

iwal
iwal

Reputation: 36

I think the problem is related to your declaration of $findme. You're passing an array of HTML elements, but in Scrolled() you're looking for one specific top offset.

The demo you provided will work if you pass an id of one specific element rather than the class identifier of all elements.

Maybe you could update the code above to pass one identifier at a time to Scrolled(). I'm not sure how to accomplish this in the context of your application, sorry.

Upvotes: 0

Related Questions