Child by scroll position

by bruth

HTML

<div><span id=position>0</span>px -> child <span id=mark>0</span></div>

<div id=parent>
</div>

CSS

#parent {
    height: 300px;
    overflow: auto;
    border: 1px solid grey;
}

#parent > * {
    padding: 5px;
    border-bottom: 1px solid grey;
}

JavaScript

var parent = $('#parent'),
    position = $('#position'),
    mark = $('#mark');

var children = [];

for (var i = 0; i < 100; i++) {
    children.push('<div>Element ' + i + '</div>');
}

parent.html(children);

var elementAtScrollTop = function(parent) {
    // Current scroll position and total scroll height
    var scrollTop = parent[0].scrollTop,
        scrollHeight = parent[0].scrollHeight;

    // Determine element that makes the dominant view of the scroll window.
    // If the top-most element is partially out of view, the following element
    // will be marked if they it has more pixels visible.
    var i,
        child,
        sibling,
        previous,
        childHeight,
        childVisibleHeight,
        childVisiblePercentage,
        totalChildHeight = 0,
        visibleThreshold = 0.25;

    var children = parent.children();
    
    for (i = 0; i < children.length; i++) {
        child = $(children[i]);
        childHeight = child.outerHeight(true);
        childVisiblePercentage = 1;

        totalChildHeight += childHeight;

        // Scroll is completely beyond child
        if (scrollTop > totalChildHeight) continue;

        // Check a sibling exists        
        if (!children[i + 1]) break;
        
        sibling = $(children[i + 1]);
        
        // Calculate the visible height of the child
        childVisibleHeight = totalChildHeight - scrollTop;
        childVisiblePercentage = childVisibleHeight / childHeight;
        
        // If at least N % is visible, use it
        if (childVisiblePercentage < visibleThreshold) {
            previous = child;
            child = sibling;
            i++;
        }
        
        break;        
    }
    return {
        position: scrollTop,
        percentage: scrollTop / scrollHeight,
        visibility: childVisiblePercentage,
        previous: previous,
        index: i,
        element: child
    };
}

parent.on('scroll', function(event) {
    var child =...