jQuery $(window).scroll事件处理程序关闭但仍在触发?

时间:2016-04-23 09:26:25

标签: javascript jquery underscore.js squarespace

我正在使用我编写的jQuery插件遇到一些奇怪的行为。基本上,当滚动浏览侧栏所属的博客帖子时,插件会使侧边栏元素粘贴到浏览器窗口的顶部。这应该仅在窗口达到特定大小(768px)或更高时发生(插件通过检查侧边栏的浮动样式来检测到这种情况)。

一切都按预期工作......直到您从大型侧边栏调整浏览器的大小是粘性的 - 小侧边栏不应该是粘性的。我的onResize函数应该会删除滚动事件处理程序,并且只有在startQuery为true时才将其添加回来(因此,如果侧边栏浮点值不是none)。我通过控制台进行了双重和三重检查:就我所知,一切正常。我甚至将console.log('scroll')添加到onScroll函数中,并且当应该删除事件处理程序时它不显示,但当我滚动浏览博客帖子时,我的侧边栏仍然变粘。

您可以在行动here中看到问题。要重新创建步骤:

  1. 将浏览器窗口的大小调整为小于768px宽并访问该页面。看到每个博客文章中的.share-bar元素在滚动时不会移动。 “滚动”未记录在控制台中。
  2. 将浏览器窗口调整为768px或更大。当您滚动浏览每个博文时,看到.share-bar元素变得粘滞,然后在滚过它时粘到帖子的底部。 “滚动”记录在控制台中。
  3. 将浏览器窗口调整为小于768像素。当您滚动浏览每篇博文时,看到.share-bar元素变得粘滞。 “滚动”未记录在控制台中。
  4. 这几乎就像删除了事件处理程序,但元素没有更新或其他东西。我确信我遗漏了一些基本的东西,但我已经研究并尝试了$(window).scroll事件问题的各种修复,但没有一个在这里工作。

    我对插件的调用:

    $('.share-bar').stickySides({ 
        'wrapper': '.post-wrapper', 
        'content': '.entry-content' });
    

    插件代码:

    ;( function ( $, window, document, undefined ) {
    
    var settings;
    var throttled;
    
    $.fn.stickySides = function( options ) {
    
        settings = $.extend( {}, $.fn.stickySides.defaults, options );
    
        // Store sidebars
        settings.selector = this.selector;
        settings.startQuery = '$("' + settings.selector + '").css(\'float\') != \'none\'';
    
        // Create debounced resize function
        var debounced = _.debounce( $.fn.stickySides.onResize, settings.wait );
        $(window).resize( debounced );
    
        // Create throttled scroll function
        throttled = _.throttle( $.fn.stickySides.onScroll, settings.wait );
        // Only continue if the start query is true
        if ( eval(settings.startQuery) == true ) {
            $(window).on( 'scroll.stickySides', throttled );    
        }
    
        return this;
    };
    
    // Define default settings
    $.fn.stickySides.defaults = {
        wrapper: 'body',
        content: '.content',
        wait: 100,
        startQuery: ''
    };
    
    $.fn.stickySides.onResize = function ( ) {
    
        $(window).off( 'scroll.stickySides' );
    
        // Only continue if the start query is true
        if ( eval(settings.startQuery) == true ) {
    
            $(window).on( 'scroll.stickySides', throttled );
    
        } else {
    
            var sides = $(settings.selector);
            sides.each ( function () {
    
                var elem = $(this);
                var content = elem.siblings( settings.content );
    
                if ( elem.css('position') == 'fixed' || elem.css('position') == 'absolute' ) {
                    elem.css( 'position', 'static' );
                }
    
                if ( content.css('margin-left') != '0px' ) {
                    content.css( 'margin-left', 0 );
                }
    
            });
    
        }
    
    };
    
    $.fn.stickySides.onScroll = function ( ) {
    
        console.log('scroll');      
        var sides = $(settings.selector);
    
        // Check each sidebar
        sides.each ( function () {
    
            var elem = $(this);
            var content = elem.siblings( settings.content );
            var wrapper = elem.closest( settings.wrapper );
    
            var elemHeight = elem.height();
            var wrapperHeight = wrapper.height();
    
            // Only continue if the wrapper is taller than the sidebar 
            if ( elemHeight >= wrapperHeight ) {
    
                return;
    
            } else {
    
                var wrapperFracs = wrapper.fracs(function (fracs) {
    
                    // Only continue if the wrapper is in view
                    if ( fracs.visible == 0 ) {
    
                        return;
    
                    } else {
    
                        // Check if the wrapper extends beyond the top of
                        // the viewport
                        var wrapperSpaceTop = fracs.rects.element.top;
    
                        // If it does, change sidebar position as appropriate
                        if ( wrapperSpaceTop > 0 ) {
    
                            var visibleWrapper = fracs.rects.document.height;
    
                            // If the visible portion of the wrapper is smaller
                            // than the height of the sidebar...
                            if ( visibleWrapper <= elemHeight ) {
    
                                // ...position the sidebar at the bottom
                                // of the wrapper
                                if ( wrapperSpaceTop != 0 ) {
    
                                    elem.css('position', 'absolute').css( 'top', (wrapperHeight - elemHeight) + content.position().top + 'px' );
    
                                } 
    
                            // Otherwise, move sidebar to appropriate position
                            } else {
    
                                elem.css('position', 'fixed').css('top', 0);
    
                            }
    
                            content.css('margin-left', elem.outerWidth());
    
                        } else {
    
                            elem.css('position', 'static');
                            content.css('margin-left', 0);
    
                        }
    
                    }
                });
    
    
            }
    
    
        });
    
    };
    
    } )( jQuery, window, document );
    

    PS:我会使用现有的插件,但我没有看到一个与我需要的功能非常接近的插件;如果你知道一个,请随时指出一个。我还没有在Mac之外测试过。是的,我知道有些页面元素在移动设备上不能很好地流动 - 例如:网站标题&amp;导航 - 还有一些与此问题无关的其他缺失项目。在我解决之前,我正在等待客户的一些反馈。

1 个答案:

答案 0 :(得分:1)

每次都会发生。在我寻求帮助后不久,我就自己弄明白了。 ;)

问题出在onScroll函数内的fracs函数中。我没有意识到它称为自己的调整大小/滚动处理程序,所以那些在我删除我的滚动处理程序时没有被绑定。我只是重新设计插件以利用fracs库的处理程序而不是调用我自己的滚动处理程序:

;( function ( $, window, document, undefined ) {

var settings;
var throttled;

$.fn.stickySides = function( options ) {

    settings = $.extend( {}, $.fn.stickySides.defaults, options );

    // Store sidebars
    settings.selector = this.selector;
    settings.startQuery = '$("' + settings.selector + '").css(\'float\') != \'none\'';

    if ( eval( settings.startQuery ) == true ) {

        $.fn.stickySides.doFracs();

    }

    // Create debounced resize function
    var debounced = _.debounce( $.fn.stickySides.onResize, settings.wait );
    $(window).resize( debounced );

    return this;
};

// Define default settings
$.fn.stickySides.defaults = {
    wrapper: 'body',
    content: '.content',
    wait: 100,
    startQuery: ''
};

$.fn.stickySides.doFracs = function ( ) {

    var sides = $(settings.selector);

    // Check each sidebar
    sides.each ( function () {

        var elem = $(this);
        var content = elem.siblings( settings.content );
        var wrapper = elem.closest( settings.wrapper );

        var elemHeight = elem.height();
        var wrapperHeight = wrapper.height();

        // Only continue if the wrapper is taller than the sidebar 
        if ( elemHeight >= wrapperHeight ) {

            return;

        } else {

            var wrapperFracs = wrapper.fracs( $.fn.stickySides.fracsCallback );

        }

    });

}

$.fn.stickySides.unbindFracs = function ( ) {

    var sides = $(settings.selector);

    // Check each sidebar
    sides.each ( function () {

        var elem = $(this);
        var content = elem.siblings( settings.content );
        var wrapper = elem.closest( settings.wrapper );


        if ( elem.css('position') == 'fixed' || elem.css('position') == 'absolute' ) {
            elem.css( 'position', 'static' );
        }

        if ( content.css('margin-left') != '0px' ) {
            content.css( 'margin-left', 0 );
        }

        wrapper.fracs('unbind');

    });

}

$.fn.stickySides.fracsCallback = function ( fracs ) {

    // Only continue if the wrapper is in view
    if ( fracs.visible == 0 ) {

        return;

    } else {

        var wrapper = $(this);
        var elem = wrapper.find(settings.selector);
        var content = elem.siblings( settings.content );

        var elemHeight = elem.height();
        var wrapperHeight = wrapper.height();

        // Check if the wrapper extends beyond the top of
        // the viewport
        var wrapperSpaceTop = fracs.rects.element.top;

        // If it does, change sidebar position as appropriate
        if ( wrapperSpaceTop > 0 ) {

            var visibleWrapper = fracs.rects.document.height;

            // If the visible portion of the wrapper is smaller
            // than the height of the sidebar...
            if ( visibleWrapper <= elemHeight ) {

                // ...position the sidebar at the bottom
                // of the wrapper
                if ( wrapperSpaceTop != 0 ) {

                    elem.css('position', 'absolute').css( 'top', (wrapperHeight - elemHeight) + content.position().top + 'px' );

                } 

            // Otherwise, move sidebar to appropriate position
            } else {

                elem.css('position', 'fixed').css('top', 0);

            }

            content.css('margin-left', elem.outerWidth());

        } else {

            elem.css('position', 'static');
            content.css('margin-left', 0);

        }

    }

}

$.fn.stickySides.onResize = function ( ) {

    // Only continue if the start query is true
    if ( eval(settings.startQuery) == true ) {

        $.fn.stickySides.doFracs();

    } else {

        $.fn.stickySides.unbindFracs();

    }

};


} )( jQuery, window, document );

瞧!问题解决了。