开发者

jQuery sticky div misbehaving

I'm using a bit of code to keep a sidebar element in view (and within the bounds of its parent) while scrolling and am having a bit of a problem. I have multiple articles on a page (approximately 10), each with it's own sidebar. The markup looks like this:

<article>
    <section class="project-details entry-content">
        <header>
            ...
        </header>
    </section>
    <section class="offset-by-four twelve columns">
        ...
    </section>
</article>

And the CSS:

article {
    padding-top: 2em;
    position: relative; }
article .project-details {
    margin: 0 10px;
    position: absolute;
    width: 220px; }

... and finally, the Javascript:

$.fn.persistent = function(options) {
    var opts = $.extend({
        duration: 0,
        lockBottom: true
    },
    options),
    elements = [];

    this.each(function() {
        var parentPaddingTop = parseInt($(this).parent().css('paddingTop'));
        $(this).data({
            'parentPaddingTop': parentPaddingTop,
            'startOffset': $(this).parent().offset().top
        }).css({
            position: 'absolute'
        });
        if (opts.lockBottom) {
            var bottomPos = $(this).parent().height() - $(this).height() + parentPaddingTop;
            if (bottomPos < 0) {
                bottomPos = 0;
            }
            $(this).data('bottomPos', bottomPos);
        }
        elements.push($(this));
    });
    $(window).scroll(function() {
        var pastStartOffset = $(document).scrollTop() > opts.startOffset;
        $.each(elements,
            function() {
                var parentPaddingTop = $(this).data('parentPaddingTop'),
                    startOffset = $(this).data('startOffset'),
                    bottomPos = $(this).data('bottomPos');
                $(this).stop();
                var objFartherThanTopPos = $(this).offset().top > startOffset,
                    objBiggerThanWindow = $(this).outerHeight() < $(window).height();
                if ((pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow) {
                    var newpos = ($(document).scrollTop() - startOffset + parentPaddingTop);
                    if (newpos > bottomPos) {
                        newpos = bottomPos;
                    }
                    if ($(document).scrollTop() < startOffset) {
                        newpos = parentPaddingTop;
                    }
                    $(this).animate({
                        top: newpos
                    }, opts.duration);
                }
            }
        );
    });
};

It's the .project-details DIV that should remain sticky, but for some reason only the first one on the page works and the rest do nothing. Occasionally the second will start to work wh开发者_开发问答ile scrolling down the page and then will fail about halfway through.

Can anyone see any glaring flaws with this code that might cause such behavior?


check the following code and make sure you understand that n is each element, using this instead a each function does not refer to the current element if that makes sense.

 this.each(function(i,n) {
        var parentPaddingTop = parseInt($(n).parent().css('paddingTop'));
        $(n).data({
            'parentPaddingTop': parentPaddingTop,
            'startOffset': $(n).parent().offset().top
        }).css({
            position: 'absolute'
        });
        if (opts.lockBottom) {
            var bottomPos = $(n).parent().height() - $(n).height() + parentPaddingTop;
            if (bottomPos < 0) {
                bottomPos = 0;
            }
            $(n).data('bottomPos', bottomPos);
        }
        elements.push($(n));
    });
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜