开发者

jQuery sticky div misbehaving

开发者 https://www.devze.com 2023-03-15 11:36 出处:网络
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)

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

精彩评论

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

关注公众号