Bootstrap affix reset not works

冷暖自知 提交于 2021-02-18 17:10:18

问题


I am trying to implement an affix in bootstrap. It shouldn't be a problem, but I want to make it responsive.

When a page has resized, some elements will hide at the top of the page, and because of change of width, I need to reset the affix and set to the new position.

I just search for it, and found an accepted solution, but it seems, it is not works.

This is what I've tried:

$(window).off('#myAffix');
$('#myAffix').removeData('bs.affix').removeClass('affix affix-top affix-bottom');
$('#myAffix').affix({
    offset: {
        top: function () {
            console.log('Offset top from: ' + $('.navbar').offset().top);
            return (this.top = $('.navbar').offset().top);
        }
    }
});

I am calling it on document.ready, and on window.resize events.

I've created a demo for it. This is the steps, how you can reproduce the problem:

  • When you open it, resize the reult window while there are 2 columns before the bordered affix, and reload the page. When you scroll down, you will see, the affix is starts to work when it need.

  • Resize the window while only the left column remains. Affix is works now also.

  • Resize the window again, while the right column appears. Now affix will trigger, when it reach the previous position, the height of the left column. That is bad.

It seems, my code is running, but has no effect on affix.

PS: Do not care about the position of the affix, I just want to fix, when / where it will be fixed.

jsFiddle here.


回答1:


There is only one change you need to do for your code to work as you wish, and this is to change the $(window).off('#myAffix'); to $(window).off('.affix');

This is the new function:

$.myFunction = function() {
    $(window).off('.affix')
    $('#myAffix').removeData('bs.affix').removeClass('affix affix-top affix-bottom');
    $('#myAffix').affix({
        offset: {
            top: function() {
                console.log('Offset top from: ' + $('.navbar').offset().top);
                return (this.top = $('.navbar').offset().top);
            }
        }
    });
};



回答2:


In your sample, you have in the HTML the .affix-top class and the data-spy="affix" attribute.

<nav class="navbar scroll-menu affix-top" data-spy="affix" id="myAffix" style="border: 1px solid #f00;">
  <ul class="nav navbar-nav" style="font-size: 10px; background: #fff;">
    <li><a href="#section1">SECTION ONE</a></li>
    <li><a href="#section2">SECTION TWO</a></li>
  </ul>
</nav>

Those are not required since the .affix-top is added dynamically by the plugin when initialized and the data-spy="affix" attribute is also not required since you are initializing it with JavaScript.

So, your HTML would be:

<nav id="myAffix" class="navbar scroll-menu" style="border: 1px solid #f00;">
  <ul class="nav navbar-nav" style="font-size: 10px; background: #fff;">
    <li><a href="#section1">SECTION ONE</a></li>
    <li><a href="#section2">SECTION TWO</a></li>
  </ul>
</nav>

Also, in the documentation it specifies the following:

Use the affix plugin via data attributes or manually with your own JavaScript. In both situations, you must provide CSS for the positioning and width of your affixed content.

That means that you should add some CSS to set the width and position of the affixed div.

.affix {
  top: 40px;
  /* This is the desired offset where the affixed div will appear */
  width: 100%;
  /* This is the desired width where the affixed div will have */
}

With the above changes, the affix works as expected, both in full screen and small screen.


But then, I stumbled into a bug!! The bug appeared when loading in full screen, and then, resizing to a small screen.

When in small screen, the plugin remembered the offset properties of the full screen initialization. The bug is that the affix plugin binds a handler in the window.scroll event that is never removed.

That is a memory leak bug (found here), and a workaround for that is mentioned in an answer.

So, instead of calling:

$(window).off('#myAffix');

you should call the following for properly removing all events created by the previous initialization

$(window).off('.affix');

To sum up, your JS would be like:

$.initAffix = function() {
  $('#myAffix').affix({
    offset: {
      top: function() {
        console.log('Offset top from: ' + $('.navbar').offset().top);
        return (this.top = $('.navbar').offset().top);
      }
    }
  });
};

$.resetAffix = function() {
  console.log('resetAffix');
  $(window).off('.affix');
  $('#myAffix').removeData('bs.affix').removeClass('affix affix-top affix-bottom');
  $.initAffix();
};

$(window).on('resize', $.resetAffix);

$.initAffix();

Here is a working demo.



来源:https://stackoverflow.com/questions/37805758/bootstrap-affix-reset-not-works

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!